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)
|
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 {
|
export function remove(block: Block, parent: ParentNode): void {
|
||||||
|
const isRoot = !parentsWithUnmountedChildren
|
||||||
|
if (isRoot) {
|
||||||
|
parentsWithUnmountedChildren = new Set()
|
||||||
|
}
|
||||||
if (block instanceof Node) {
|
if (block instanceof Node) {
|
||||||
parent.removeChild(block)
|
parent.removeChild(block)
|
||||||
} else if (isVaporComponent(block)) {
|
} else if (isVaporComponent(block)) {
|
||||||
|
@ -143,4 +155,10 @@ export function remove(block: Block, parent: ParentNode): void {
|
||||||
;(block as DynamicFragment).scope!.stop()
|
;(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,
|
unregisterHMR,
|
||||||
warn,
|
warn,
|
||||||
} from '@vue/runtime-dom'
|
} from '@vue/runtime-dom'
|
||||||
import { type Block, insert, isBlock, remove } from './block'
|
import {
|
||||||
|
type Block,
|
||||||
|
insert,
|
||||||
|
isBlock,
|
||||||
|
parentsWithUnmountedChildren,
|
||||||
|
remove,
|
||||||
|
} from './block'
|
||||||
import {
|
import {
|
||||||
markRaw,
|
markRaw,
|
||||||
pauseTracking,
|
pauseTracking,
|
||||||
|
@ -33,7 +39,14 @@ import {
|
||||||
resetTracking,
|
resetTracking,
|
||||||
unref,
|
unref,
|
||||||
} from '@vue/reactivity'
|
} 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 {
|
import {
|
||||||
type DynamicPropsSource,
|
type DynamicPropsSource,
|
||||||
type RawProps,
|
type RawProps,
|
||||||
|
@ -465,24 +478,45 @@ export function mountComponent(
|
||||||
|
|
||||||
export function unmountComponent(
|
export function unmountComponent(
|
||||||
instance: VaporComponentInstance,
|
instance: VaporComponentInstance,
|
||||||
parent?: ParentNode,
|
parentNode?: ParentNode,
|
||||||
): void {
|
): void {
|
||||||
if (instance.isMounted && !instance.isUnmounted) {
|
if (instance.isMounted && !instance.isUnmounted) {
|
||||||
if (__DEV__ && instance.type.__hmrId) {
|
if (__DEV__ && instance.type.__hmrId) {
|
||||||
unregisterHMR(instance)
|
unregisterHMR(instance)
|
||||||
}
|
}
|
||||||
if (instance.bum) invokeArrayFns(instance.bum)
|
if (instance.bum) {
|
||||||
|
invokeArrayFns(instance.bum)
|
||||||
|
}
|
||||||
|
|
||||||
instance.scope.stop()
|
instance.scope.stop()
|
||||||
|
|
||||||
for (const c of instance.children) {
|
for (const c of instance.children) {
|
||||||
unmountComponent(c)
|
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) {
|
if (instance.um) {
|
||||||
queuePostFlushCb(() => invokeArrayFns(instance.um!))
|
queuePostFlushCb(() => invokeArrayFns(instance.um!))
|
||||||
}
|
}
|
||||||
instance.isUnmounted = true
|
instance.isUnmounted = true
|
||||||
} else if (parent) {
|
} else if (parentNode) {
|
||||||
remove(instance.block, parent)
|
remove(instance.block, parentNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue