Browse Source

fix(compiler-core): prefix dynamic keys on v-memo elements (#14922)

close #14920
edison 5 days ago
parent
commit
68e978e3e7

+ 21 - 0
packages/compiler-core/__tests__/transforms/vMemo.spec.ts

@@ -21,6 +21,27 @@ describe('compiler: v-memo transform', () => {
     expect(compile(`<div v-memo="[x]"></div>`)).toMatchSnapshot()
   })
 
+  test('on normal element with dynamic key', () => {
+    const code = compile(`<div v-memo="[updateKey]" :key="updateKey"></div>`)
+
+    expect(code).toContain(`_withMemo([_ctx.updateKey]`)
+    expect(code).toContain(`{ key: _ctx.updateKey }`)
+  })
+
+  test('on normal element with dynamic key nested in v-for', () => {
+    const code = compile(
+      `<div v-for="item in items">
+        <div
+          v-memo="[item.id, updateKey]"
+          :key="get(item, updateKey)"
+        >{{ item }}</div>
+      </div>`,
+    )
+
+    expect(code).toContain(`_withMemo([item.id, _ctx.updateKey]`)
+    expect(code).toContain(`key: _ctx.get(item, _ctx.updateKey)`)
+  })
+
   test('on component', () => {
     expect(compile(`<Comp v-memo="[x]"></Comp>`)).toMatchSnapshot()
   })

+ 2 - 0
packages/compiler-core/src/transform.ts

@@ -119,6 +119,7 @@ export interface TransformContext
   hoist(exp: string | JSChildNode | ArrayExpression): SimpleExpressionNode
   cache(exp: JSChildNode, isVNode?: boolean, inVOnce?: boolean): CacheExpression
   constantCache: WeakMap<TemplateChildNode, ConstantTypes>
+  vForMemoKeyedNodes: WeakSet<ElementNode>
 
   // 2.x Compat only
   filters?: Set<string>
@@ -187,6 +188,7 @@ export function createTransformContext(
     imports: [],
     cached: [],
     constantCache: new WeakMap(),
+    vForMemoKeyedNodes: new WeakSet(),
     temps: 0,
     identifiers: Object.create(null),
     scopes: {

+ 1 - 0
packages/compiler-core/src/transforms/transformExpression.ts

@@ -70,6 +70,7 @@ export const transformExpression: NodeTransform = (node, context) => {
           // key has been processed in transformFor(vMemo + vFor)
           !(
             memo &&
+            context.vForMemoKeyedNodes.has(node) &&
             arg &&
             arg.type === NodeTypes.SIMPLE_EXPRESSION &&
             arg.content === 'key'

+ 3 - 0
packages/compiler-core/src/transforms/vFor.ts

@@ -92,6 +92,9 @@ export const transformFor: NodeTransform = createStructuralDirectiveTransform(
                 keyProperty.value as SimpleExpressionNode,
                 context,
               )
+          if (memo) {
+            context.vForMemoKeyedNodes.add(node)
+          }
         }
       }