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() const n4 = t0()
_renderEffect(() => _setText(n4, _ctx1[0].value+_ctx0[0].value)) _renderEffect(() => _setText(n4, _ctx1[0].value+_ctx0[0].value))
return n4 return n4
}) }, null, null, n5)
_insert(n2, n5) _insert(n2, n5)
return n5 return n5
}) })

View File

@ -70,7 +70,7 @@ export function render(_ctx) {
const n0 = _createFor(() => (_ctx.list), (_ctx0) => { const n0 = _createFor(() => (_ctx.list), (_ctx0) => {
const n2 = t0() const n2 = t0()
return n2 return n2
}, null, null, null, true) }, null, null, null, null, true)
return n0 return n0
}" }"
`; `;

View File

@ -16,7 +16,18 @@ export function genFor(
context: CodegenContext, context: CodegenContext,
): CodeFragment[] { ): CodeFragment[] {
const { vaporHelper } = context 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 isDestructureAssignment = false
let rawValue: string | null = null let rawValue: string | null = null
@ -61,6 +72,7 @@ export function genFor(
blockFn, blockFn,
genCallback(keyProp), genCallback(keyProp),
genCallback(memo), genCallback(memo),
container != null && `n${container}`,
false, // todo: hydrationNode false, // todo: hydrationNode
once && 'true', once && 'true',
), ),

View File

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

View File

@ -56,6 +56,15 @@ export function processFor(
return (): void => { return (): void => {
exitBlock() 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({ context.registerOperation({
type: IRNodeTypes.FOR, type: IRNodeTypes.FOR,
id, id,
@ -67,6 +76,7 @@ export function processFor(
render, render,
once: context.inVOnce, once: context.inVOnce,
memo: memo && memo.exp, memo: memo && memo.exp,
container,
}) })
} }
} }

View File

@ -38,6 +38,7 @@ export const createFor = (
renderItem: (block: ForBlock['state']) => Block, renderItem: (block: ForBlock['state']) => Block,
getKey?: (item: any, key: any, index?: number) => any, getKey?: (item: any, key: any, index?: number) => any,
getMemo?: (item: any, key: any, index?: number) => any[], getMemo?: (item: any, key: any, index?: number) => any[],
container?: ParentNode,
hydrationNode?: Node, hydrationNode?: Node,
once?: boolean, once?: boolean,
): Fragment => { ): Fragment => {
@ -45,7 +46,11 @@ export const createFor = (
let oldBlocks: ForBlock[] = [] let oldBlocks: ForBlock[] = []
let newBlocks: ForBlock[] let newBlocks: ForBlock[]
let parent: ParentNode | undefined | null let parent: ParentNode | undefined | null
const parentAnchor = __DEV__ ? createComment('for') : createTextNode() const parentAnchor = container
? undefined
: __DEV__
? createComment('for')
: createTextNode()
const ref: Fragment = { const ref: Fragment = {
nodes: oldBlocks, nodes: oldBlocks,
[fragmentKey]: true, [fragmentKey]: true,
@ -71,15 +76,23 @@ export const createFor = (
isMounted = true isMounted = true
mountList(source) mountList(source)
} else { } else {
parent = parent || parentAnchor.parentNode parent = parent || container || parentAnchor!.parentNode
if (!oldLength) { if (!oldLength) {
// fast path for all new // fast path for all new
mountList(source) mountList(source)
} else if (!newLength) { } else if (!newLength) {
// 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 // fast path for clearing
for (let i = 0; i < oldLength; i++) { for (let i = 0; i < oldLength; i++) {
unmount(oldBlocks[i]) unmount(oldBlocks[i])
} }
}
} else if (!getKey) { } else if (!getKey) {
// unkeyed fast path // unkeyed fast path
const commonLength = Math.min(newLength, oldLength) const commonLength = Math.min(newLength, oldLength)
@ -239,13 +252,16 @@ export const createFor = (
} }
} }
ref.nodes = [(oldBlocks = newBlocks), parentAnchor] ref.nodes = [(oldBlocks = newBlocks)]
if (parentAnchor) {
ref.nodes.push(parentAnchor)
}
} }
function mount( function mount(
source: any, source: any,
idx: number, idx: number,
anchor: Node = parentAnchor, anchor: Node | undefined = parentAnchor,
): ForBlock { ): ForBlock {
const scope = effectScope() const scope = effectScope()