feat(core): adjust attrs fallthrough behavior

This commit is contained in:
Evan You
2019-10-25 12:12:17 -04:00
parent d76cfba7fb
commit 8edfbf9df9
8 changed files with 175 additions and 26 deletions

View File

@@ -3,15 +3,31 @@ import {
FunctionalComponent,
Data
} from './component'
import { VNode, normalizeVNode, createVNode, Comment } from './vnode'
import {
VNode,
normalizeVNode,
createVNode,
Comment,
cloneVNode
} from './vnode'
import { ShapeFlags } from './shapeFlags'
import { handleError, ErrorCodes } from './errorHandling'
import { PatchFlags } from '@vue/shared'
import { PatchFlags, EMPTY_OBJ } from '@vue/shared'
import { warn } from './warning'
// mark the current rendering instance for asset resolution (e.g.
// resolveComponent, resolveDirective) during render
export let currentRenderingInstance: ComponentInternalInstance | null = null
// dev only flag to track whether $attrs was used during render.
// If $attrs was used during render then the warning for failed attrs
// fallthrough can be suppressed.
let accessedAttrs: boolean = false
export function markAttrsAccessed() {
accessedAttrs = true
}
export function renderComponentRoot(
instance: ComponentInternalInstance
): VNode {
@@ -27,6 +43,9 @@ export function renderComponentRoot(
let result
currentRenderingInstance = instance
if (__DEV__) {
accessedAttrs = false
}
try {
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
result = normalizeVNode(instance.render!.call(renderProxy))
@@ -43,6 +62,27 @@ export function renderComponentRoot(
: render(props, null as any /* we know it doesn't need it */)
)
}
// attr merging
if (
Component.props != null &&
Component.inheritAttrs !== false &&
attrs !== EMPTY_OBJ &&
Object.keys(attrs).length
) {
if (
result.shapeFlag & ShapeFlags.ELEMENT ||
result.shapeFlag & ShapeFlags.COMPONENT
) {
result = cloneVNode(result, attrs)
} else if (__DEV__ && !accessedAttrs) {
warn(
`Extraneous non-props attributes (${Object.keys(attrs).join(',')}) ` +
`were passed to component but could not be automatically inhertied ` +
`because component renders fragment or text root nodes.`
)
}
}
} catch (err) {
handleError(err, instance, ErrorCodes.RENDER_FUNCTION)
result = createVNode(Comment)