test(runtime-core): tests for vnode hooks
This commit is contained in:
parent
ebc1ca8eff
commit
811f28a7d1
98
packages/runtime-core/__tests__/vnodeHooks.spec.ts
Normal file
98
packages/runtime-core/__tests__/vnodeHooks.spec.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import {
|
||||||
|
h,
|
||||||
|
render,
|
||||||
|
nodeOps,
|
||||||
|
VNodeProps,
|
||||||
|
TestElement,
|
||||||
|
NodeTypes,
|
||||||
|
VNode
|
||||||
|
} from '@vue/runtime-test'
|
||||||
|
|
||||||
|
describe('renderer: vnode hooks', () => {
|
||||||
|
function assertHooks(hooks: VNodeProps, vnode1: VNode, vnode2: VNode) {
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
render(vnode1, root)
|
||||||
|
expect(hooks.onVnodeBeforeMount).toHaveBeenCalledWith(vnode1, null)
|
||||||
|
expect(hooks.onVnodeMounted).toHaveBeenCalledWith(vnode1, null)
|
||||||
|
expect(hooks.onVnodeBeforeUpdate).not.toHaveBeenCalled()
|
||||||
|
expect(hooks.onVnodeUpdated).not.toHaveBeenCalled()
|
||||||
|
expect(hooks.onVnodeBeforeUnmount).not.toHaveBeenCalled()
|
||||||
|
expect(hooks.onVnodeUnmounted).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
// update
|
||||||
|
render(vnode2, root)
|
||||||
|
expect(hooks.onVnodeBeforeMount).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeMounted).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeBeforeUpdate).toHaveBeenCalledWith(vnode2, vnode1)
|
||||||
|
expect(hooks.onVnodeUpdated).toHaveBeenCalledWith(vnode2, vnode1)
|
||||||
|
expect(hooks.onVnodeBeforeUnmount).not.toHaveBeenCalled()
|
||||||
|
expect(hooks.onVnodeUnmounted).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
// unmount
|
||||||
|
render(null, root)
|
||||||
|
expect(hooks.onVnodeBeforeMount).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeMounted).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeBeforeUpdate).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeUpdated).toHaveBeenCalledTimes(1)
|
||||||
|
expect(hooks.onVnodeBeforeUnmount).toHaveBeenCalledWith(vnode2, null)
|
||||||
|
expect(hooks.onVnodeUnmounted).toHaveBeenCalledWith(vnode2, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should work on element', () => {
|
||||||
|
const hooks: VNodeProps = {
|
||||||
|
onVnodeBeforeMount: jest.fn(),
|
||||||
|
onVnodeMounted: jest.fn(),
|
||||||
|
onVnodeBeforeUpdate: jest.fn(vnode => {
|
||||||
|
expect((vnode.el as TestElement).children[0]).toMatchObject({
|
||||||
|
type: NodeTypes.TEXT,
|
||||||
|
text: 'foo'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
onVnodeUpdated: jest.fn(vnode => {
|
||||||
|
expect((vnode.el as TestElement).children[0]).toMatchObject({
|
||||||
|
type: NodeTypes.TEXT,
|
||||||
|
text: 'bar'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
onVnodeBeforeUnmount: jest.fn(),
|
||||||
|
onVnodeUnmounted: jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertHooks(hooks, h('div', hooks, 'foo'), h('div', hooks, 'bar'))
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should work on component', () => {
|
||||||
|
const Comp = (props: { msg: string }) => props.msg
|
||||||
|
|
||||||
|
const hooks: VNodeProps = {
|
||||||
|
onVnodeBeforeMount: jest.fn(),
|
||||||
|
onVnodeMounted: jest.fn(),
|
||||||
|
onVnodeBeforeUpdate: jest.fn(vnode => {
|
||||||
|
expect(vnode.el as TestElement).toMatchObject({
|
||||||
|
type: NodeTypes.TEXT,
|
||||||
|
text: 'foo'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
onVnodeUpdated: jest.fn(vnode => {
|
||||||
|
expect(vnode.el as TestElement).toMatchObject({
|
||||||
|
type: NodeTypes.TEXT,
|
||||||
|
text: 'bar'
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
onVnodeBeforeUnmount: jest.fn(),
|
||||||
|
onVnodeUnmounted: jest.fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertHooks(
|
||||||
|
hooks,
|
||||||
|
h(Comp, {
|
||||||
|
...hooks,
|
||||||
|
msg: 'foo'
|
||||||
|
}),
|
||||||
|
h(Comp, {
|
||||||
|
...hooks,
|
||||||
|
msg: 'bar'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
@ -1152,6 +1152,7 @@ function baseCreateRenderer<
|
|||||||
const nextTree = renderComponentRoot(instance)
|
const nextTree = renderComponentRoot(instance)
|
||||||
const prevTree = instance.subTree
|
const prevTree = instance.subTree
|
||||||
instance.subTree = nextTree
|
instance.subTree = nextTree
|
||||||
|
next.el = vnode.el
|
||||||
// beforeUpdate hook
|
// beforeUpdate hook
|
||||||
if (bu !== null) {
|
if (bu !== null) {
|
||||||
invokeHooks(bu)
|
invokeHooks(bu)
|
||||||
@ -1673,36 +1674,40 @@ function baseCreateRenderer<
|
|||||||
setRef(ref, null, parentComponent, null)
|
setRef(ref, null, parentComponent, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((vnodeHook = props && props.onVnodeBeforeUnmount) != null) {
|
||||||
|
invokeVNodeHook(vnodeHook, parentComponent, vnode)
|
||||||
|
}
|
||||||
|
|
||||||
if (shapeFlag & ShapeFlags.COMPONENT) {
|
if (shapeFlag & ShapeFlags.COMPONENT) {
|
||||||
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
|
if (shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
|
||||||
;(parentComponent!.sink as KeepAliveSink).deactivate(vnode)
|
;(parentComponent!.sink as KeepAliveSink).deactivate(vnode)
|
||||||
} else {
|
} else {
|
||||||
unmountComponent(vnode.component!, parentSuspense, doRemove)
|
unmountComponent(vnode.component!, parentSuspense, doRemove)
|
||||||
}
|
}
|
||||||
return
|
} else {
|
||||||
}
|
if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
|
||||||
|
vnode.suspense!.unmount(parentSuspense, doRemove)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
|
if (shouldInvokeDirs) {
|
||||||
vnode.suspense!.unmount(parentSuspense, doRemove)
|
invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((vnodeHook = props && props.onVnodeBeforeUnmount) != null) {
|
if (dynamicChildren != null) {
|
||||||
invokeVNodeHook(vnodeHook, parentComponent, vnode)
|
// fast path for block nodes: only need to unmount dynamic children.
|
||||||
}
|
unmountChildren(dynamicChildren, parentComponent, parentSuspense)
|
||||||
if (shouldInvokeDirs) {
|
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
invokeDirectiveHook(vnode, null, parentComponent, 'beforeUnmount')
|
unmountChildren(
|
||||||
}
|
children as HostVNode[],
|
||||||
|
parentComponent,
|
||||||
|
parentSuspense
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (dynamicChildren != null) {
|
if (doRemove) {
|
||||||
// fast path for block nodes: only need to unmount dynamic children.
|
remove(vnode)
|
||||||
unmountChildren(dynamicChildren, parentComponent, parentSuspense)
|
}
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
|
||||||
unmountChildren(children as HostVNode[], parentComponent, parentSuspense)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doRemove) {
|
|
||||||
remove(vnode)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
Loading…
Reference in New Issue
Block a user