mirror of https://github.com/vuejs/core.git
wip(vapor): optimize unmounted children removal
This commit is contained in:
parent
76e8d2c4d0
commit
bcb9209c4c
|
@ -126,7 +126,19 @@ export function prepend(parent: ParentNode, ...blocks: Block[]): void {
|
|||
while (i--) insert(blocks[i], parent, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized children removal: record all parents with unmounted children
|
||||
* during each root remove call, and update their children list by filtering
|
||||
* unmounted children
|
||||
*/
|
||||
export let parentsWithUnmountedChildren: Set<VaporComponentInstance> | null =
|
||||
null
|
||||
|
||||
export function remove(block: Block, parent: ParentNode): void {
|
||||
const isRoot = !parentsWithUnmountedChildren
|
||||
if (isRoot) {
|
||||
parentsWithUnmountedChildren = new Set()
|
||||
}
|
||||
if (block instanceof Node) {
|
||||
parent.removeChild(block)
|
||||
} else if (isVaporComponent(block)) {
|
||||
|
@ -143,4 +155,10 @@ export function remove(block: Block, parent: ParentNode): void {
|
|||
;(block as DynamicFragment).scope!.stop()
|
||||
}
|
||||
}
|
||||
if (isRoot) {
|
||||
for (const i of parentsWithUnmountedChildren!) {
|
||||
i.children = i.children.filter(n => !n.isUnmounted)
|
||||
}
|
||||
parentsWithUnmountedChildren = null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,13 @@ import {
|
|||
unregisterHMR,
|
||||
warn,
|
||||
} from '@vue/runtime-dom'
|
||||
import { type Block, insert, isBlock, remove } from './block'
|
||||
import {
|
||||
type Block,
|
||||
insert,
|
||||
isBlock,
|
||||
parentsWithUnmountedChildren,
|
||||
remove,
|
||||
} from './block'
|
||||
import {
|
||||
markRaw,
|
||||
pauseTracking,
|
||||
|
@ -33,7 +39,14 @@ import {
|
|||
resetTracking,
|
||||
unref,
|
||||
} from '@vue/reactivity'
|
||||
import { EMPTY_OBJ, invokeArrayFns, isFunction, isString } from '@vue/shared'
|
||||
import {
|
||||
EMPTY_ARR,
|
||||
EMPTY_OBJ,
|
||||
invokeArrayFns,
|
||||
isFunction,
|
||||
isString,
|
||||
remove as removeItem,
|
||||
} from '@vue/shared'
|
||||
import {
|
||||
type DynamicPropsSource,
|
||||
type RawProps,
|
||||
|
@ -465,24 +478,45 @@ export function mountComponent(
|
|||
|
||||
export function unmountComponent(
|
||||
instance: VaporComponentInstance,
|
||||
parent?: ParentNode,
|
||||
parentNode?: ParentNode,
|
||||
): void {
|
||||
if (instance.isMounted && !instance.isUnmounted) {
|
||||
if (__DEV__ && instance.type.__hmrId) {
|
||||
unregisterHMR(instance)
|
||||
}
|
||||
if (instance.bum) invokeArrayFns(instance.bum)
|
||||
if (instance.bum) {
|
||||
invokeArrayFns(instance.bum)
|
||||
}
|
||||
|
||||
instance.scope.stop()
|
||||
|
||||
for (const c of instance.children) {
|
||||
unmountComponent(c)
|
||||
}
|
||||
if (parent) remove(instance.block, parent)
|
||||
instance.children = EMPTY_ARR as any
|
||||
|
||||
if (parentNode) {
|
||||
// root remove: need to both remove this instance's DOM nodes
|
||||
// and also remove it from the parent's children list.
|
||||
remove(instance.block, parentNode)
|
||||
const parentInstance = instance.parent
|
||||
if (isVaporComponent(parentInstance)) {
|
||||
if (parentsWithUnmountedChildren) {
|
||||
// for optimize children removal
|
||||
parentsWithUnmountedChildren.add(parentInstance)
|
||||
} else {
|
||||
removeItem(parentInstance.children, instance)
|
||||
}
|
||||
instance.parent = null
|
||||
}
|
||||
}
|
||||
|
||||
if (instance.um) {
|
||||
queuePostFlushCb(() => invokeArrayFns(instance.um!))
|
||||
}
|
||||
instance.isUnmounted = true
|
||||
} else if (parent) {
|
||||
remove(instance.block, parent)
|
||||
} else if (parentNode) {
|
||||
remove(instance.block, parentNode)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue