]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-vapor): fast path for clear all children
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 5 Oct 2024 13:23:37 +0000 (21:23 +0800)
committer三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sat, 5 Oct 2024 13:27:57 +0000 (21:27 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/__snapshots__/vOnce.spec.ts.snap
packages/compiler-vapor/src/generators/for.ts
packages/compiler-vapor/src/ir/index.ts
packages/compiler-vapor/src/transforms/vFor.ts
packages/runtime-vapor/src/apiCreateFor.ts

index 49b1f5734581833990a8aaf01d804eac800a830f..6780439eca0f35473d0aab85cbc0d7c5a954935b 100644 (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
   })
index 68fe53dd887bd0ad46570b045730c21f7ad1f49e..2a2f1692096b7698691cf87951b9463f086f6cd9 100644 (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
 }"
 `;
index 21fb2ed02ab8d6593f63c823fe726cb285ff6435..ddfd61e1b65f7f5eac1b3e64b3f8052f2d01db91 100644 (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',
     ),
index f4157a516ee19088d81613a0352edc83e5ee279f..8e10ab0a7c2c3b8d6b97e208a98bf698d85a79b4 100644 (file)
@@ -86,6 +86,7 @@ export interface ForIRNode extends BaseIRNode, IRFor {
   keyProp?: SimpleExpressionNode
   render: BlockIRNode
   once: boolean
+  container?: number
 }
 
 export interface SetPropIRNode extends BaseIRNode {
index a5ed245c201d29808bf8122505a42144e1d8b501..735c086bf273d5e351451248a4d3cc017e91a829 100644 (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,
     })
   }
 }
index 29913ac0497c61fbab5fba2c7fa9b454a0f7a92b..dabeb27e75a684b0a282710d42f46b9dd863b4bd 100644 (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()