import {
|
tip,
|
hasOwn,
|
isDef,
|
isUndef,
|
hyphenate,
|
formatComponentName
|
} from 'core/util/index'
|
import type { Component } from 'types/component'
|
import type { VNodeData } from 'types/vnode'
|
|
export function extractPropsFromVNodeData(
|
data: VNodeData,
|
Ctor: typeof Component,
|
tag?: string
|
): object | undefined {
|
// we are only extracting raw values here.
|
// validation and default values are handled in the child
|
// component itself.
|
const propOptions = Ctor.options.props
|
if (isUndef(propOptions)) {
|
return
|
}
|
const res = {}
|
const { attrs, props } = data
|
if (isDef(attrs) || isDef(props)) {
|
for (const key in propOptions) {
|
const altKey = hyphenate(key)
|
if (__DEV__) {
|
const keyInLowerCase = key.toLowerCase()
|
if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) {
|
tip(
|
`Prop "${keyInLowerCase}" is passed to component ` +
|
`${formatComponentName(
|
// @ts-expect-error tag is string
|
tag || Ctor
|
)}, but the declared prop name is` +
|
` "${key}". ` +
|
`Note that HTML attributes are case-insensitive and camelCased ` +
|
`props need to use their kebab-case equivalents when using in-DOM ` +
|
`templates. You should probably use "${altKey}" instead of "${key}".`
|
)
|
}
|
}
|
checkProp(res, props, key, altKey, true) ||
|
checkProp(res, attrs, key, altKey, false)
|
}
|
}
|
return res
|
}
|
|
function checkProp(
|
res: Object,
|
hash: Object | undefined,
|
key: string,
|
altKey: string,
|
preserve: boolean
|
): boolean {
|
if (isDef(hash)) {
|
if (hasOwn(hash, key)) {
|
res[key] = hash[key]
|
if (!preserve) {
|
delete hash[key]
|
}
|
return true
|
} else if (hasOwn(hash, altKey)) {
|
res[key] = hash[altKey]
|
if (!preserve) {
|
delete hash[altKey]
|
}
|
return true
|
}
|
}
|
return false
|
}
|