Browse Source

perf(templateRef): avoid double render when using template ref on v-for

close #9908
Evan You 2 years ago
parent
commit
de4d2e2143
1 changed files with 9 additions and 7 deletions
  1. 9 7
      packages/runtime-core/src/rendererTemplateRef.ts

+ 9 - 7
packages/runtime-core/src/rendererTemplateRef.ts

@@ -81,9 +81,10 @@ export function setRef(
   } else {
     const _isString = isString(ref)
     const _isRef = isRef(ref)
+    const isVFor = rawRef.f
     if (_isString || _isRef) {
       const doSet = () => {
-        if (rawRef.f) {
+        if (isVFor) {
           const existing = _isString
             ? hasOwn(setupState, ref)
               ? setupState[ref]
@@ -118,14 +119,15 @@ export function setRef(
           warn('Invalid template ref type:', ref, `(${typeof ref})`)
         }
       }
-      if (value) {
-        // #1789: for non-null values, set them after render
-        // null values means this is unmount and it should not overwrite another
-        // ref with the same key
+      // #9908 ref on v-for mutates the same array for both mount and unmount
+      // and should be done together
+      if (isUnmount || isVFor) {
+        doSet()
+      } else {
+        // #1789: set new refs in a post job so that they don't get overwritten
+        // by unmounting ones.
         ;(doSet as SchedulerJob).id = -1
         queuePostRenderEffect(doSet, parentSuspense)
-      } else {
-        doSet()
       }
     } else if (__DEV__) {
       warn('Invalid template ref type:', ref, `(${typeof ref})`)