fix(runtime-core): fix duplicated unmount traversal in optimized mode
fix #2169
This commit is contained in:
parent
5dbd6b36a0
commit
376883d1cf
@ -14,7 +14,8 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
withCtx,
|
withCtx,
|
||||||
renderSlot
|
renderSlot,
|
||||||
|
onBeforeUnmount
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
import { PatchFlags, SlotFlags } from '@vue/shared'
|
import { PatchFlags, SlotFlags } from '@vue/shared'
|
||||||
|
|
||||||
@ -449,4 +450,29 @@ describe('renderer: optimized mode', () => {
|
|||||||
|
|
||||||
expect(inner(root)).toBe('<div><p>1</p></div>')
|
expect(inner(root)).toBe('<div><p>1</p></div>')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #2169
|
||||||
|
// block
|
||||||
|
// - dynamic child (1)
|
||||||
|
// - component (2)
|
||||||
|
// When unmounting (1), we know we are in optimized mode so no need to further
|
||||||
|
// traverse unmount its children
|
||||||
|
test('should not perform unnecessary unmount traversals', () => {
|
||||||
|
const spy = jest.fn()
|
||||||
|
const Child = {
|
||||||
|
setup() {
|
||||||
|
onBeforeUnmount(spy)
|
||||||
|
return () => 'child'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Parent = () => (
|
||||||
|
openBlock(),
|
||||||
|
createBlock('div', null, [
|
||||||
|
createVNode('div', { style: {} }, [createVNode(Child)], 4 /* STYLE */)
|
||||||
|
])
|
||||||
|
)
|
||||||
|
render(h(Parent), root)
|
||||||
|
render(null, root)
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -213,7 +213,8 @@ type UnmountFn = (
|
|||||||
vnode: VNode,
|
vnode: VNode,
|
||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
doRemove?: boolean
|
doRemove?: boolean,
|
||||||
|
optimized?: boolean
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
type RemoveFn = (vnode: VNode) => void
|
type RemoveFn = (vnode: VNode) => void
|
||||||
@ -223,6 +224,7 @@ type UnmountChildrenFn = (
|
|||||||
parentComponent: ComponentInternalInstance | null,
|
parentComponent: ComponentInternalInstance | null,
|
||||||
parentSuspense: SuspenseBoundary | null,
|
parentSuspense: SuspenseBoundary | null,
|
||||||
doRemove?: boolean,
|
doRemove?: boolean,
|
||||||
|
optimized?: boolean,
|
||||||
start?: number
|
start?: number
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
@ -1647,7 +1649,14 @@ function baseCreateRenderer(
|
|||||||
}
|
}
|
||||||
if (oldLength > newLength) {
|
if (oldLength > newLength) {
|
||||||
// remove old
|
// remove old
|
||||||
unmountChildren(c1, parentComponent, parentSuspense, true, commonLength)
|
unmountChildren(
|
||||||
|
c1,
|
||||||
|
parentComponent,
|
||||||
|
parentSuspense,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
commonLength
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// mount new
|
// mount new
|
||||||
mountChildren(
|
mountChildren(
|
||||||
@ -1968,7 +1977,8 @@ function baseCreateRenderer(
|
|||||||
vnode,
|
vnode,
|
||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
doRemove = false
|
doRemove = false,
|
||||||
|
optimized = false
|
||||||
) => {
|
) => {
|
||||||
const {
|
const {
|
||||||
type,
|
type,
|
||||||
@ -2016,8 +2026,14 @@ function baseCreateRenderer(
|
|||||||
(patchFlag > 0 && patchFlag & PatchFlags.STABLE_FRAGMENT))
|
(patchFlag > 0 && patchFlag & PatchFlags.STABLE_FRAGMENT))
|
||||||
) {
|
) {
|
||||||
// fast path for block nodes: only need to unmount dynamic children.
|
// fast path for block nodes: only need to unmount dynamic children.
|
||||||
unmountChildren(dynamicChildren, parentComponent, parentSuspense)
|
unmountChildren(
|
||||||
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
dynamicChildren,
|
||||||
|
parentComponent,
|
||||||
|
parentSuspense,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
} else if (!optimized && shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
|
||||||
unmountChildren(children as VNode[], parentComponent, parentSuspense)
|
unmountChildren(children as VNode[], parentComponent, parentSuspense)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2149,10 +2165,11 @@ function baseCreateRenderer(
|
|||||||
parentComponent,
|
parentComponent,
|
||||||
parentSuspense,
|
parentSuspense,
|
||||||
doRemove = false,
|
doRemove = false,
|
||||||
|
optimized = false,
|
||||||
start = 0
|
start = 0
|
||||||
) => {
|
) => {
|
||||||
for (let i = start; i < children.length; i++) {
|
for (let i = start; i < children.length; i++) {
|
||||||
unmount(children[i], parentComponent, parentSuspense, doRemove)
|
unmount(children[i], parentComponent, parentSuspense, doRemove, optimized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user