|
6 | 6 | capitalize,
|
7 | 7 | hyphenate,
|
8 | 8 | isFunction,
|
9 |
| - def |
| 9 | + extend |
10 | 10 | } from '@vue/shared'
|
11 |
| -import { ComponentInternalInstance } from './component' |
| 11 | +import { ComponentInternalInstance, Component } from './component' |
12 | 12 | import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
|
13 | 13 | import { warn } from './warning'
|
14 | 14 | import { normalizePropsOptions } from './componentProps'
|
@@ -43,7 +43,7 @@ export function emit(
|
43 | 43 | const props = instance.vnode.props || EMPTY_OBJ
|
44 | 44 |
|
45 | 45 | if (__DEV__) {
|
46 |
| - const options = normalizeEmitsOptions(instance.type.emits) |
| 46 | + const options = normalizeEmitsOptions(instance.type) |
47 | 47 | if (options) {
|
48 | 48 | if (!(event in options)) {
|
49 | 49 | const propsOptions = normalizePropsOptions(instance.type)[0]
|
@@ -84,34 +84,52 @@ export function emit(
|
84 | 84 | }
|
85 | 85 | }
|
86 | 86 |
|
87 |
| -export function normalizeEmitsOptions( |
88 |
| - options: EmitsOptions | undefined |
| 87 | +function normalizeEmitsOptions( |
| 88 | + comp: Component |
89 | 89 | ): ObjectEmitsOptions | undefined {
|
90 |
| - if (!options) { |
91 |
| - return |
92 |
| - } else if (isArray(options)) { |
93 |
| - if ((options as any)._n) { |
94 |
| - return (options as any)._n |
| 90 | + if (hasOwn(comp, '__emits')) { |
| 91 | + return comp.__emits |
| 92 | + } |
| 93 | + |
| 94 | + const raw = comp.emits |
| 95 | + let normalized: ObjectEmitsOptions = {} |
| 96 | + |
| 97 | + // apply mixin/extends props |
| 98 | + let hasExtends = false |
| 99 | + if (__FEATURE_OPTIONS__ && !isFunction(comp)) { |
| 100 | + if (comp.extends) { |
| 101 | + hasExtends = true |
| 102 | + extend(normalized, normalizeEmitsOptions(comp.extends)) |
95 | 103 | }
|
96 |
| - const normalized: ObjectEmitsOptions = {} |
97 |
| - options.forEach(key => (normalized[key] = null)) |
98 |
| - def(options, '_n', normalized) |
99 |
| - return normalized |
| 104 | + if (comp.mixins) { |
| 105 | + hasExtends = true |
| 106 | + comp.mixins.forEach(m => extend(normalized, normalizeEmitsOptions(m))) |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + if (!raw && !hasExtends) { |
| 111 | + return (comp.__emits = undefined) |
| 112 | + } |
| 113 | + |
| 114 | + if (isArray(raw)) { |
| 115 | + raw.forEach(key => (normalized[key] = null)) |
100 | 116 | } else {
|
101 |
| - return options |
| 117 | + extend(normalized, raw) |
102 | 118 | }
|
| 119 | + return (comp.__emits = normalized) |
103 | 120 | }
|
104 | 121 |
|
105 | 122 | // Check if an incoming prop key is a declared emit event listener.
|
106 | 123 | // e.g. With `emits: { click: null }`, props named `onClick` and `onclick` are
|
107 | 124 | // both considered matched listeners.
|
108 |
| -export function isEmitListener(emits: EmitsOptions, key: string): boolean { |
| 125 | +export function isEmitListener(comp: Component, key: string): boolean { |
| 126 | + if (!isOn(key)) { |
| 127 | + return false |
| 128 | + } |
| 129 | + const emits = normalizeEmitsOptions(comp) |
109 | 130 | return (
|
110 |
| - isOn(key) && |
111 |
| - (hasOwn( |
112 |
| - (emits = normalizeEmitsOptions(emits) as ObjectEmitsOptions), |
113 |
| - key[2].toLowerCase() + key.slice(3) |
114 |
| - ) || |
| 131 | + !!emits && |
| 132 | + (hasOwn(emits, key[2].toLowerCase() + key.slice(3)) || |
115 | 133 | hasOwn(emits, key.slice(2)))
|
116 | 134 | )
|
117 | 135 | }
|
0 commit comments