feat(compile-core): handle falsy dynamic args for v-on and v-bind (#2393)

fix #2388
This commit is contained in:
ᴜɴвʏтᴇ
2020-10-20 05:15:53 +08:00
committed by GitHub
parent 7390487c7d
commit 052a621762
15 changed files with 96 additions and 71 deletions

View File

@@ -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. ` +

View File

@@ -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) {

View File

@@ -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
}

View File

@@ -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'

View File

@@ -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]

View File

@@ -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]
}
}