fix(runtime-core): rework vnode hooks handling

- peroperly support directive on components (e.g. <foo v-show="x">)
- consistently invoke raw vnode hooks on component vnodes (fix #684)
This commit is contained in:
Evan You
2020-02-10 13:15:36 -05:00
parent 8a87074df0
commit cfadb98011
4 changed files with 204 additions and 26 deletions

View File

@@ -46,6 +46,7 @@ export function renderComponentRoot(
props,
slots,
attrs,
vnodeHooks,
emit
} = instance
@@ -92,14 +93,23 @@ export function renderComponentRoot(
}
}
// inherit vnode hooks
if (vnodeHooks !== EMPTY_OBJ) {
result = cloneVNode(result, vnodeHooks)
}
// inherit directives
if (vnode.dirs != null) {
if (__DEV__ && !isElementRoot(result)) {
warn(
`Runtime directive used on component with non-element root node. ` +
`The directives will not function as intended.`
)
}
result.dirs = vnode.dirs
}
// inherit transition data
if (vnode.transition != null) {
if (
__DEV__ &&
!(result.shapeFlag & ShapeFlags.COMPONENT) &&
!(result.shapeFlag & ShapeFlags.ELEMENT) &&
result.type !== Comment
) {
if (__DEV__ && !isElementRoot(result)) {
warn(
`Component inside <Transition> renders non-element root node ` +
`that cannot be animated.`
@@ -115,6 +125,14 @@ export function renderComponentRoot(
return result
}
function isElementRoot(vnode: VNode) {
return (
vnode.shapeFlag & ShapeFlags.COMPONENT ||
vnode.shapeFlag & ShapeFlags.ELEMENT ||
vnode.type === Comment // potential v-if branch switch
)
}
export function shouldUpdateComponent(
prevVNode: VNode,
nextVNode: VNode,
@@ -137,6 +155,11 @@ export function shouldUpdateComponent(
return true
}
// force child update on runtime directive usage on component vnode.
if (nextVNode.dirs != null) {
return true
}
if (patchFlag > 0) {
if (patchFlag & PatchFlags.DYNAMIC_SLOTS) {
// slot content that references values that might have changed,
@@ -174,6 +197,7 @@ export function shouldUpdateComponent(
}
return hasPropsChanged(prevProps, nextProps)
}
return false
}