Skip to content

Commit b7ca9e5

Browse files
committed
feat(runtime-vapor): fast path for clear all children
1 parent 3867942 commit b7ca9e5

File tree

4 files changed

+47
-8
lines changed

4 files changed

+47
-8
lines changed

packages/compiler-vapor/src/generators/for.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,18 @@ export function genFor(
1616
context: CodegenContext,
1717
): CodeFragment[] {
1818
const { vaporHelper } = context
19-
const { source, value, key, index, render, keyProp, once, id, memo } = oper
19+
const {
20+
source,
21+
value,
22+
key,
23+
index,
24+
render,
25+
keyProp,
26+
once,
27+
id,
28+
memo,
29+
container,
30+
} = oper
2031

2132
let isDestructureAssignment = false
2233
let rawValue: string | null = null
@@ -61,6 +72,7 @@ export function genFor(
6172
blockFn,
6273
genCallback(keyProp),
6374
genCallback(memo),
75+
container != null && `n${container}`,
6476
false, // todo: hydrationNode
6577
once && 'true',
6678
),

packages/compiler-vapor/src/ir/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export interface ForIRNode extends BaseIRNode, IRFor {
8686
keyProp?: SimpleExpressionNode
8787
render: BlockIRNode
8888
once: boolean
89+
container?: number
8990
}
9091

9192
export interface SetPropIRNode extends BaseIRNode {

packages/compiler-vapor/src/transforms/vFor.ts

+10
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@ export function processFor(
5656

5757
return (): void => {
5858
exitBlock()
59+
const { parent } = context
60+
let container: number | undefined
61+
if (
62+
parent &&
63+
parent.block.node !== parent.node &&
64+
parent.node.children.length === 1
65+
) {
66+
container = parent.reference()
67+
}
5968
context.registerOperation({
6069
type: IRNodeTypes.FOR,
6170
id,
@@ -67,6 +76,7 @@ export function processFor(
6776
render,
6877
once: context.inVOnce,
6978
memo: memo && memo.exp,
79+
container,
7080
})
7181
}
7282
}

packages/runtime-vapor/src/apiCreateFor.ts

+23-7
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,19 @@ export const createFor = (
3838
renderItem: (block: ForBlock['state']) => Block,
3939
getKey?: (item: any, key: any, index?: number) => any,
4040
getMemo?: (item: any, key: any, index?: number) => any[],
41+
container?: ParentNode,
4142
hydrationNode?: Node,
4243
once?: boolean,
4344
): Fragment => {
4445
let isMounted = false
4546
let oldBlocks: ForBlock[] = []
4647
let newBlocks: ForBlock[]
4748
let parent: ParentNode | undefined | null
48-
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
49+
const parentAnchor = container
50+
? undefined
51+
: __DEV__
52+
? createComment('for')
53+
: createTextNode()
4954
const ref: Fragment = {
5055
nodes: oldBlocks,
5156
[fragmentKey]: true,
@@ -71,14 +76,22 @@ export const createFor = (
7176
isMounted = true
7277
mountList(source)
7378
} else {
74-
parent = parent || parentAnchor.parentNode
79+
parent = parent || container || parentAnchor!.parentNode
7580
if (!oldLength) {
7681
// fast path for all new
7782
mountList(source)
7883
} else if (!newLength) {
79-
// fast path for clearing
80-
for (let i = 0; i < oldLength; i++) {
81-
unmount(oldBlocks[i])
84+
// fast path for all removed
85+
if (container) {
86+
container.textContent = ''
87+
for (let i = 0; i < oldLength; i++) {
88+
oldBlocks[i].scope.stop()
89+
}
90+
} else {
91+
// fast path for clearing
92+
for (let i = 0; i < oldLength; i++) {
93+
unmount(oldBlocks[i])
94+
}
8295
}
8396
} else if (!getKey) {
8497
// unkeyed fast path
@@ -239,13 +252,16 @@ export const createFor = (
239252
}
240253
}
241254

242-
ref.nodes = [(oldBlocks = newBlocks), parentAnchor]
255+
ref.nodes = [(oldBlocks = newBlocks)]
256+
if (parentAnchor) {
257+
ref.nodes.push(parentAnchor)
258+
}
243259
}
244260

245261
function mount(
246262
source: any,
247263
idx: number,
248-
anchor: Node = parentAnchor,
264+
anchor: Node | undefined = parentAnchor,
249265
): ForBlock {
250266
const scope = effectScope()
251267

0 commit comments

Comments
 (0)