Skip to content

Commit

Permalink
feat(runtime-vapor): fast path for clear all children
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Oct 5, 2024
1 parent 3867942 commit c1c316d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function render(_ctx) {
const n4 = t0()
_renderEffect(() => _setText(n4, _ctx1[0].value+_ctx0[0].value))
return n4
})
}, null, null, n5)
_insert(n2, n5)
return n5
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
const n2 = t0()
return n2
}, null, null, null, true)
}, null, null, null, null, true)
return n0
}"
`;
Expand Down
14 changes: 13 additions & 1 deletion packages/compiler-vapor/src/generators/for.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ export function genFor(
context: CodegenContext,
): CodeFragment[] {
const { vaporHelper } = context
const { source, value, key, index, render, keyProp, once, id, memo } = oper
const {
source,
value,
key,
index,
render,
keyProp,
once,
id,
memo,
container,
} = oper

let isDestructureAssignment = false
let rawValue: string | null = null
Expand Down Expand Up @@ -61,6 +72,7 @@ export function genFor(
blockFn,
genCallback(keyProp),
genCallback(memo),
container != null && `n${container}`,
false, // todo: hydrationNode
once && 'true',
),
Expand Down
1 change: 1 addition & 0 deletions packages/compiler-vapor/src/ir/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export interface ForIRNode extends BaseIRNode, IRFor {
keyProp?: SimpleExpressionNode
render: BlockIRNode
once: boolean
container?: number
}

export interface SetPropIRNode extends BaseIRNode {
Expand Down
10 changes: 10 additions & 0 deletions packages/compiler-vapor/src/transforms/vFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ export function processFor(

return (): void => {
exitBlock()
const { parent } = context
let container: number | undefined
if (
parent &&
parent.block.node !== parent.node &&
parent.node.children.length === 1
) {
container = parent.reference()
}
context.registerOperation({
type: IRNodeTypes.FOR,
id,
Expand All @@ -67,6 +76,7 @@ export function processFor(
render,
once: context.inVOnce,
memo: memo && memo.exp,
container,
})
}
}
30 changes: 23 additions & 7 deletions packages/runtime-vapor/src/apiCreateFor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ export const createFor = (
renderItem: (block: ForBlock['state']) => Block,
getKey?: (item: any, key: any, index?: number) => any,
getMemo?: (item: any, key: any, index?: number) => any[],
container?: ParentNode,
hydrationNode?: Node,
once?: boolean,
): Fragment => {
let isMounted = false
let oldBlocks: ForBlock[] = []
let newBlocks: ForBlock[]
let parent: ParentNode | undefined | null
const parentAnchor = __DEV__ ? createComment('for') : createTextNode()
const parentAnchor = container
? undefined
: __DEV__
? createComment('for')
: createTextNode()
const ref: Fragment = {
nodes: oldBlocks,
[fragmentKey]: true,
Expand All @@ -71,14 +76,22 @@ export const createFor = (
isMounted = true
mountList(source)
} else {
parent = parent || parentAnchor.parentNode
parent = parent || container || parentAnchor!.parentNode
if (!oldLength) {
// fast path for all new
mountList(source)
} else if (!newLength) {
// fast path for clearing
for (let i = 0; i < oldLength; i++) {
unmount(oldBlocks[i])
// fast path for all removed
if (container) {
container.textContent = ''
for (let i = 0; i < oldLength; i++) {
oldBlocks[i].scope.stop()
}
} else {
// fast path for clearing
for (let i = 0; i < oldLength; i++) {
unmount(oldBlocks[i])
}
}
} else if (!getKey) {
// unkeyed fast path
Expand Down Expand Up @@ -239,13 +252,16 @@ export const createFor = (
}
}

ref.nodes = [(oldBlocks = newBlocks), parentAnchor]
ref.nodes = [(oldBlocks = newBlocks)]
if (parentAnchor) {
ref.nodes.push(parentAnchor)
}
}

function mount(
source: any,
idx: number,
anchor: Node = parentAnchor,
anchor: Node | undefined = parentAnchor,
): ForBlock {
const scope = effectScope()

Expand Down

0 comments on commit c1c316d

Please sign in to comment.