const res: Data = {}
if (raw) {
for (const key in raw) {
- if (key === 'key' || key === 'ref' || key === 'slot') {
+ // key, ref, slots are reserved
+ if (key === 'key' || key === 'ref' || key === 'slots') {
continue
}
- if (hasDeclaredProps) {
- if (options.hasOwnProperty(key)) {
- if (__DEV__) {
- validateProp(key, raw[key], options[key], Component)
- }
- res[key] = raw[key]
- } else {
- // when props are explicitly declared, any non-matching prop is
- // extracted into attrs instead.
- ;(res.attrs || (res.attrs = {}))[key] = raw[key]
- }
+ // class, style & nativeOn are always extracted into a separate `attrs`
+ // object, which can then be merged onto child component root.
+ // in addition, if the component has explicitly declared props, then
+ // any non-matching props are extracted into `attrs` as well.
+ let isNativeOn
+ if (
+ key === 'class' ||
+ key === 'style' ||
+ (isNativeOn = key.startsWith('nativeOn')) ||
+ (hasDeclaredProps && !options.hasOwnProperty(key))
+ ) {
+ const newKey = isNativeOn ? 'on' + key.slice(8) : key
+ ;(res.attrs || (res.attrs = {}))[newKey] = raw[key]
} else {
+ if (__DEV__ && hasDeclaredProps && options.hasOwnProperty(key)) {
+ validateProp(key, raw[key], options[key], Component)
+ }
res[key] = raw[key]
}
}
(flags & VNodeFlags.COMPONENT || flags & VNodeFlags.ELEMENT)
) {
const parentData = componentVNode.data
- if (parentData != null && inheritAttrs !== false) {
- let extraData: any = null
- for (const key in parentData) {
- // attrs/class/style bindings on parentVNode are merged down to child
- // component root,
- // nativeOn* handlers are merged to child root as normal on* handlers.
- // cloneVNode contains special logic for merging these props with
- // existing values.
- if (key === 'attrs') {
- extraData = extraData || {}
- const { attrs } = parentData
- for (const attr in attrs) {
- extraData[attr] = attrs[attr]
- }
- } else if (key === 'class' || key === 'style') {
- ;(extraData || (extraData = {}))[key] = parentData[key]
- } else if (key.startsWith('nativeOn')) {
- ;(extraData || (extraData = {}))['on' + key.slice(8)] =
- parentData[key]
- }
- }
- if (extraData) {
- vnode = cloneVNode(vnode, extraData)
- }
+ if (inheritAttrs !== false && parentData && parentData.attrs) {
+ vnode = cloneVNode(vnode, parentData.attrs)
}
if (vnode.el) {
vnode = cloneVNode(vnode)