]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(templateRef): simplify template ref handling and remove old ref declarations
authordaiwei <daiwei521@126.com>
Wed, 3 Sep 2025 03:40:25 +0000 (11:40 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 3 Sep 2025 03:40:25 +0000 (11:40 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/transformTemplateRef.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/transformTemplateRef.spec.ts
packages/compiler-vapor/src/generators/operation.ts
packages/compiler-vapor/src/generators/templateRef.ts
packages/compiler-vapor/src/ir/index.ts
packages/compiler-vapor/src/transforms/transformTemplateRef.ts
packages/runtime-vapor/__tests__/dom/templateRef.spec.ts
packages/runtime-vapor/src/apiTemplateRef.ts

index 7184446fc09d0a7bd42ab12550f4892df3fbf955..e40f3007e424eaa2926ae71bd7d05189f482f103 100644 (file)
@@ -7,8 +7,7 @@ const t0 = _template("<div></div>", true)
 export function render(_ctx) {
   const _setTemplateRef = _createTemplateRefSetter()
   const n0 = t0()
-  let r0
-  _renderEffect(() => r0 = _setTemplateRef(n0, _ctx.foo, r0))
+  _renderEffect(() => _setTemplateRef(n0, _ctx.foo))
   return n0
 }"
 `;
@@ -20,14 +19,13 @@ const t0 = _template("<div></div>", true)
 export function render(_ctx) {
   const _setTemplateRef = _createTemplateRefSetter()
   const n0 = t0()
-  let r0
   _renderEffect(() => {
     const _foo = _ctx.foo
-    r0 = _setTemplateRef(n0, bar => {
+    _setTemplateRef(n0, bar => {
         _foo.value = bar
         ;({ baz: _ctx.baz } = bar)
         console.log(_foo.value, _ctx.baz)
-      }, r0)
+      })
   })
   return n0
 }"
@@ -41,7 +39,7 @@ export function render(_ctx) {
   const _setTemplateRef = _createTemplateRefSetter()
   const n0 = _createFor(() => ([1,2,3]), (_for_item0) => {
     const n2 = t0()
-    _setTemplateRef(n2, "foo", void 0, true)
+    _setTemplateRef(n2, "foo", true)
     return n2
   }, undefined, 4)
   return n0
index 2c883d10cc6cd16e822b321ac50c6c91feba7320..97afce3a7ae19be60ce807221d896a37936dcfcb 100644 (file)
@@ -67,12 +67,6 @@ describe('compiler: template ref transform', () => {
       flags: DynamicFlag.REFERENCED,
     })
     expect(ir.template).toEqual(['<div></div>'])
-    expect(ir.block.operation).toMatchObject([
-      {
-        type: IRNodeTypes.DECLARE_OLD_REF,
-        id: 0,
-      },
-    ])
     expect(ir.block.effect).toMatchObject([
       {
         operations: [
@@ -89,7 +83,7 @@ describe('compiler: template ref transform', () => {
     ])
     expect(code).matchSnapshot()
     expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
-    expect(code).contains('_setTemplateRef(n0, _ctx.foo, r0)')
+    expect(code).contains('_setTemplateRef(n0, _ctx.foo)')
   })
 
   test('function ref', () => {
@@ -105,12 +99,6 @@ describe('compiler: template ref transform', () => {
       flags: DynamicFlag.REFERENCED,
     })
     expect(ir.template).toEqual(['<div></div>'])
-    expect(ir.block.operation).toMatchObject([
-      {
-        type: IRNodeTypes.DECLARE_OLD_REF,
-        id: 0,
-      },
-    ])
     expect(ir.block.effect).toMatchObject([
       {
         operations: [
@@ -130,7 +118,7 @@ describe('compiler: template ref transform', () => {
         _foo.value = bar
         ;({ baz: _ctx.baz } = bar)
         console.log(_foo.value, _ctx.baz)
-      }, r0)`)
+      })`)
   })
 
   test('ref + v-if', () => {
@@ -178,6 +166,6 @@ describe('compiler: template ref transform', () => {
     ])
     expect(code).matchSnapshot()
     expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
-    expect(code).contains('_setTemplateRef(n2, "foo", void 0, true)')
+    expect(code).contains('_setTemplateRef(n2, "foo", true)')
   })
 })
index 13ce5477cc1705908d777c3d75ae18089a82c809..9fbccfd77b4806e2f965c008449937fff4630f8e 100644 (file)
@@ -12,7 +12,7 @@ import { genFor } from './for'
 import { genSetHtml } from './html'
 import { genIf } from './if'
 import { genDynamicProps, genSetProp } from './prop'
-import { genDeclareOldRef, genSetTemplateRef } from './templateRef'
+import { genSetTemplateRef } from './templateRef'
 import { genGetTextChild, genSetText } from './text'
 import {
   type CodeFragment,
@@ -79,8 +79,6 @@ export function genOperation(
       return genFor(oper, context)
     case IRNodeTypes.CREATE_COMPONENT_NODE:
       return genCreateComponent(oper, context)
-    case IRNodeTypes.DECLARE_OLD_REF:
-      return genDeclareOldRef(oper)
     case IRNodeTypes.SLOT_OUTLET_NODE:
       return genSlotOutlet(oper, context)
     case IRNodeTypes.DIRECTIVE:
index af8facc57b1f80b1342b16bb31ea8d192ef21e54..dd572c05077c756d5c3c91b7edf5153764b6e850 100644 (file)
@@ -1,6 +1,6 @@
 import { genExpression } from './expression'
 import type { CodegenContext } from '../generate'
-import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
+import type { SetTemplateRefIRNode } from '../ir'
 import { type CodeFragment, NEWLINE, genCall } from './utils'
 import { BindingTypes, type SimpleExpressionNode } from '@vue/compiler-dom'
 
@@ -12,21 +12,15 @@ export function genSetTemplateRef(
 ): CodeFragment[] {
   return [
     NEWLINE,
-    oper.effect && `r${oper.element} = `,
     ...genCall(
       setTemplateRefIdent, // will be generated in root scope
       `n${oper.element}`,
       genRefValue(oper.value, context),
-      oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
       oper.refFor && 'true',
     ),
   ]
 }
 
-export function genDeclareOldRef(oper: DeclareOldRefIRNode): CodeFragment[] {
-  return [NEWLINE, `let r${oper.id}`]
-}
-
 function genRefValue(value: SimpleExpressionNode, context: CodegenContext) {
   // in inline mode there is no setupState object, so we can't use string
   // keys to set the ref. Instead, we need to transform it to pass the
index 18f0139ab568e4f082c88241bca7f6a87b53bb98..15cc9ab0054f98e5530606c2154605de2c0119a4 100644 (file)
@@ -29,7 +29,6 @@ export enum IRNodeTypes {
   SLOT_OUTLET_NODE,
 
   DIRECTIVE,
-  DECLARE_OLD_REF, // consider make it more general
 
   IF,
   FOR,
@@ -197,11 +196,6 @@ export interface CreateComponentIRNode extends BaseIRNode {
   anchor?: number
 }
 
-export interface DeclareOldRefIRNode extends BaseIRNode {
-  type: IRNodeTypes.DECLARE_OLD_REF
-  id: number
-}
-
 export interface SlotOutletIRNode extends BaseIRNode {
   type: IRNodeTypes.SLOT_OUTLET_NODE
   id: number
@@ -232,7 +226,6 @@ export type OperationNode =
   | IfIRNode
   | ForIRNode
   | CreateComponentIRNode
-  | DeclareOldRefIRNode
   | SlotOutletIRNode
   | GetTextChildIRNode
 
index 9fa7c09bf58b5d50a7593b3144aff884e10ad252..111af9fe94b2984f809c1b3a30a8faec464ec36c 100644 (file)
@@ -29,11 +29,6 @@ export const transformTemplateRef: NodeTransform = (node, context) => {
   return () => {
     const id = context.reference()
     const effect = !isConstantExpression(value)
-    effect &&
-      context.registerOperation({
-        type: IRNodeTypes.DECLARE_OLD_REF,
-        id,
-      })
     context.registerEffect([value], {
       type: IRNodeTypes.SET_TEMPLATE_REF,
       element: id,
index 4e8a1a9253c2a41d07d673c55eb25b5d5d2d93bc..7fa0ea0c3871c5755f07ce50c3a4cd5601df80cc 100644 (file)
@@ -1,4 +1,3 @@
-import type { NodeRef } from '../../src/apiTemplateRef'
 import {
   child,
   createComponent,
@@ -64,9 +63,9 @@ describe('api: template ref', () => {
       },
       render() {
         const n0 = t0()
-        let r0: NodeRef | undefined
+        const setRef = createTemplateRefSetter()
         renderEffect(() => {
-          r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
+          setRef(n0 as Element, refKey.value)
         })
         return n0
       },
@@ -137,9 +136,9 @@ describe('api: template ref', () => {
     const { render } = define({
       render() {
         const n0 = t0()
-        let r0: NodeRef | undefined
+        const setRef = createTemplateRefSetter()
         renderEffect(() => {
-          r0 = createTemplateRefSetter()(n0 as Element, fn.value, r0)
+          setRef(n0 as Element, fn.value)
         })
         return n0
       },
@@ -165,11 +164,12 @@ describe('api: template ref', () => {
     const t0 = template('<div></div>')
     const { render } = define({
       render() {
+        const setRef = createTemplateRefSetter()
         const n0 = createIf(
           () => toggle.value,
           () => {
             const n1 = t0()
-            createTemplateRefSetter()(n1 as Element, fn)
+            setRef(n1 as Element, fn)
             return n1
           },
         )
@@ -217,9 +217,9 @@ describe('api: template ref', () => {
         fooEl = useTemplateRef('foo')
         barEl = useTemplateRef('bar')
         const n0 = t0()
-        let r0: NodeRef | undefined
+        const setRef = createTemplateRefSetter()
         renderEffect(() => {
-          r0 = createTemplateRefSetter()(n0 as Element, refKey.value, r0)
+          setRef(n0 as Element, refKey.value)
         })
         return n0
       },
@@ -324,21 +324,12 @@ describe('api: template ref', () => {
         const instance = currentInstance!
         const n0 = t0()
         const n1 = t1()
-        let r0: NodeRef | undefined
-        let r1: NodeRef | undefined
+        const setRef = createTemplateRefSetter()
         renderEffect(() => {
-          r0 = createTemplateRefSetter()(
-            n0 as Element,
-            refToggle.value ? 'foo' : 'bar',
-            r0,
-          )
+          setRef(n0 as Element, refToggle.value ? 'foo' : 'bar')
         })
         renderEffect(() => {
-          r1 = createTemplateRefSetter()(
-            n1 as Element,
-            refToggle.value ? 'bar' : 'foo',
-            r1,
-          )
+          setRef(n1 as Element, refToggle.value ? 'bar' : 'foo')
         })
         watchEffect(
           () => {
@@ -422,6 +413,7 @@ describe('api: template ref', () => {
     const t1 = template('<li></li>')
     const { render } = define({
       render() {
+        const setRef = createTemplateRefSetter()
         const n0 = createIf(
           () => show.value,
           () => {
@@ -430,12 +422,7 @@ describe('api: template ref', () => {
               () => list,
               item => {
                 const n1 = t1()
-                createTemplateRefSetter()(
-                  n1 as Element,
-                  listRefs,
-                  undefined,
-                  true,
-                )
+                setRef(n1 as Element, listRefs, true)
                 renderEffect(() => {
                   setElementText(n1, item)
                 })
@@ -484,6 +471,7 @@ describe('api: template ref', () => {
         return { listRefs }
       },
       render() {
+        const setRef = createTemplateRefSetter()
         const n0 = createIf(
           () => show.value,
           () => {
@@ -492,12 +480,7 @@ describe('api: template ref', () => {
               () => list,
               item => {
                 const n1 = t1()
-                createTemplateRefSetter()(
-                  n1 as Element,
-                  'listRefs',
-                  undefined,
-                  true,
-                )
+                setRef(n1 as Element, 'listRefs', true)
                 renderEffect(() => {
                   setElementText(n1, item)
                 })
@@ -548,16 +531,12 @@ describe('api: template ref', () => {
         const n0 = t0()
         const n1 = n0.firstChild
         const n2 = n1!.nextSibling!
+        const setRef = createTemplateRefSetter()
         const n3 = createFor(
           () => list.value,
           item => {
             const n4 = t1()
-            createTemplateRefSetter()(
-              n4 as Element,
-              'listRefs',
-              undefined,
-              true,
-            )
+            setRef(n4 as Element, 'listRefs', true)
             renderEffect(() => {
               setElementText(n4, item)
             })
index a14f373e7def428d3dc890c5ff61ddcfeb930077..c3d73e6ab47d5fc72c78c419c679e35061460975 100644 (file)
@@ -29,13 +29,17 @@ export type RefEl = Element | VaporComponentInstance
 export type setRefFn = (
   el: RefEl,
   ref: NodeRef,
-  oldRef?: NodeRef,
   refFor?: boolean,
 ) => NodeRef | undefined
 
 export function createTemplateRefSetter(): setRefFn {
   const instance = currentInstance as VaporComponentInstance
-  return (...args) => setRef(instance, ...args)
+  const oldRefMap = new WeakMap<RefEl, NodeRef | undefined>()
+  return (el, ref, refFor) => {
+    const oldRef = setRef(instance, el, ref, oldRefMap.get(el), refFor)
+    oldRefMap.set(el, oldRef)
+    return oldRef
+  }
 }
 
 /**