feat(runtime-vapor): fast path for clear all children

This commit is contained in:
三咲智子 Kevin Deng 2024-10-05 21:23:37 +08:00
parent 3867942ddb
commit c1c316d392
No known key found for this signature in database
6 changed files with 49 additions and 10 deletions

View File

@ -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
})

View File

@ -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
}"
`;

View File

@ -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
@ -61,6 +72,7 @@ export function genFor(
blockFn,
genCallback(keyProp),
genCallback(memo),
container != null && `n${container}`,
false, // todo: hydrationNode
once && 'true',
),

View File

@ -86,6 +86,7 @@ export interface ForIRNode extends BaseIRNode, IRFor {
keyProp?: SimpleExpressionNode
render: BlockIRNode
once: boolean
container?: number
}
export interface SetPropIRNode extends BaseIRNode {

View File

@ -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,
@ -67,6 +76,7 @@ export function processFor(
render,
once: context.inVOnce,
memo: memo && memo.exp,
container,
})
}
}

View File

@ -38,6 +38,7 @@ 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 => {
@ -45,7 +46,11 @@ export const createFor = (
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,
@ -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
@ -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()