feat(compile-core): handle falsy dynamic args for v-on and v-bind (#2393)
fix #2388
This commit is contained in:
@@ -1,15 +1,15 @@
|
||||
import {
|
||||
ComponentInternalInstance,
|
||||
LifecycleHooks,
|
||||
currentInstance,
|
||||
setCurrentInstance,
|
||||
isInSSRComponentSetup
|
||||
isInSSRComponentSetup,
|
||||
LifecycleHooks,
|
||||
setCurrentInstance
|
||||
} from './component'
|
||||
import { ComponentPublicInstance } from './componentPublicInstance'
|
||||
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
|
||||
import { warn } from './warning'
|
||||
import { capitalize } from '@vue/shared'
|
||||
import { pauseTracking, resetTracking, DebuggerEvent } from '@vue/reactivity'
|
||||
import { toHandlerKey } from '@vue/shared'
|
||||
import { DebuggerEvent, pauseTracking, resetTracking } from '@vue/reactivity'
|
||||
|
||||
export { onActivated, onDeactivated } from './components/KeepAlive'
|
||||
|
||||
@@ -49,9 +49,7 @@ export function injectHook(
|
||||
}
|
||||
return wrappedHook
|
||||
} else if (__DEV__) {
|
||||
const apiName = `on${capitalize(
|
||||
ErrorTypeStrings[type].replace(/ hook$/, '')
|
||||
)}`
|
||||
const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, ''))
|
||||
warn(
|
||||
`${apiName} is called when there is no active component instance to be ` +
|
||||
`associated with. ` +
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
isArray,
|
||||
isOn,
|
||||
hasOwn,
|
||||
camelize,
|
||||
EMPTY_OBJ,
|
||||
capitalize,
|
||||
hyphenate,
|
||||
isFunction,
|
||||
toHandlerKey,
|
||||
extend,
|
||||
camelize
|
||||
hasOwn,
|
||||
hyphenate,
|
||||
isArray,
|
||||
isFunction,
|
||||
isOn
|
||||
} from '@vue/shared'
|
||||
import {
|
||||
ComponentInternalInstance,
|
||||
@@ -56,10 +56,10 @@ export function emit(
|
||||
} = instance
|
||||
if (emitsOptions) {
|
||||
if (!(event in emitsOptions)) {
|
||||
if (!propsOptions || !(`on` + capitalize(event) in propsOptions)) {
|
||||
if (!propsOptions || !(toHandlerKey(event) in propsOptions)) {
|
||||
warn(
|
||||
`Component emitted event "${event}" but it is neither declared in ` +
|
||||
`the emits option nor as an "on${capitalize(event)}" prop.`
|
||||
`the emits option nor as an "${toHandlerKey(event)}" prop.`
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -82,7 +82,7 @@ export function emit(
|
||||
|
||||
if (__DEV__) {
|
||||
const lowerCaseEvent = event.toLowerCase()
|
||||
if (lowerCaseEvent !== event && props[`on` + capitalize(lowerCaseEvent)]) {
|
||||
if (lowerCaseEvent !== event && props[toHandlerKey(lowerCaseEvent)]) {
|
||||
warn(
|
||||
`Event "${lowerCaseEvent}" is emitted in component ` +
|
||||
`${formatComponentName(
|
||||
@@ -97,12 +97,12 @@ export function emit(
|
||||
}
|
||||
|
||||
// convert handler name to camelCase. See issue #2249
|
||||
let handlerName = `on${capitalize(camelize(event))}`
|
||||
let handlerName = toHandlerKey(camelize(event))
|
||||
let handler = props[handlerName]
|
||||
// for v-model update:xxx events, also trigger kebab-case equivalent
|
||||
// for props passed via kebab-case
|
||||
if (!handler && event.startsWith('update:')) {
|
||||
handlerName = `on${capitalize(hyphenate(event))}`
|
||||
handlerName = toHandlerKey(hyphenate(event))
|
||||
handler = props[handlerName]
|
||||
}
|
||||
if (!handler) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isObject, capitalize } from '@vue/shared'
|
||||
import { toHandlerKey, isObject } from '@vue/shared'
|
||||
import { warn } from '../warning'
|
||||
|
||||
/**
|
||||
@@ -12,7 +12,7 @@ export function toHandlers(obj: Record<string, any>): Record<string, any> {
|
||||
return ret
|
||||
}
|
||||
for (const key in obj) {
|
||||
ret[`on${capitalize(key)}`] = obj[key]
|
||||
ret[toHandlerKey(key)] = obj[key]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -240,7 +240,12 @@ export {
|
||||
createCommentVNode,
|
||||
createStaticVNode
|
||||
} from './vnode'
|
||||
export { toDisplayString, camelize, capitalize } from '@vue/shared'
|
||||
export {
|
||||
toDisplayString,
|
||||
camelize,
|
||||
capitalize,
|
||||
toHandlerKey
|
||||
} from '@vue/shared'
|
||||
|
||||
// For test-utils
|
||||
export { transformVNodeArgs } from './vnode'
|
||||
|
||||
@@ -1070,6 +1070,7 @@ function baseCreateRenderer(
|
||||
) => {
|
||||
if (oldProps !== newProps) {
|
||||
for (const key in newProps) {
|
||||
// empty string is not valid prop
|
||||
if (isReservedProp(key)) continue
|
||||
const next = newProps[key]
|
||||
const prev = oldProps[key]
|
||||
|
||||
@@ -644,7 +644,7 @@ export function mergeProps(...args: (Data & VNodeProps)[]) {
|
||||
? [].concat(existing as any, toMerge[key] as any)
|
||||
: incoming
|
||||
}
|
||||
} else {
|
||||
} else if (key !== '') {
|
||||
ret[key] = toMerge[key]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user