diff --git a/packages/compiler-core/__tests__/transforms/vFor.spec.ts b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
index 1fc19c902..411aba2c4 100644
--- a/packages/compiler-core/__tests__/transforms/vFor.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/vFor.spec.ts
@@ -582,6 +582,61 @@ describe('compiler: v-for', () => {
]
})
})
+
+ test('element v-for key expression prefixing', () => {
+ const {
+ node: { codegenNode }
+ } = parseWithForTransform(
+ '
test
',
+ { prefixIdentifiers: true }
+ )
+ const innerBlock = codegenNode.children.arguments[1].returns
+ expect(innerBlock).toMatchObject({
+ type: NodeTypes.VNODE_CALL,
+ tag: `"div"`,
+ props: createObjectMatcher({
+ key: {
+ type: NodeTypes.COMPOUND_EXPRESSION,
+ children: [
+ // should prefix outer scope references
+ { content: `_ctx.itemKey` },
+ `(`,
+ // should NOT prefix in scope variables
+ { content: `item` },
+ `)`
+ ]
+ }
+ })
+ })
+ })
+
+ // #2085
+ test('template v-for key expression prefixing', () => {
+ const {
+ node: { codegenNode }
+ } = parseWithForTransform(
+ 'test',
+ { prefixIdentifiers: true }
+ )
+ const innerBlock = codegenNode.children.arguments[1].returns
+ expect(innerBlock).toMatchObject({
+ type: NodeTypes.VNODE_CALL,
+ tag: FRAGMENT,
+ props: createObjectMatcher({
+ key: {
+ type: NodeTypes.COMPOUND_EXPRESSION,
+ children: [
+ // should prefix outer scope references
+ { content: `_ctx.itemKey` },
+ `(`,
+ // should NOT prefix in scope variables
+ { content: `item` },
+ `)`
+ ]
+ }
+ })
+ })
+ })
})
describe('codegen', () => {
diff --git a/packages/compiler-core/src/transforms/vFor.ts b/packages/compiler-core/src/transforms/vFor.ts
index 99ab91044..63c4458c1 100644
--- a/packages/compiler-core/src/transforms/vFor.ts
+++ b/packages/compiler-core/src/transforms/vFor.ts
@@ -54,6 +54,27 @@ export const transformFor = createStructuralDirectiveTransform(
forNode.source
]) as ForRenderListExpression
const keyProp = findProp(node, `key`)
+ const keyProperty = keyProp
+ ? createObjectProperty(
+ `key`,
+ keyProp.type === NodeTypes.ATTRIBUTE
+ ? createSimpleExpression(keyProp.value!.content, true)
+ : keyProp.exp!
+ )
+ : null
+
+ if (!__BROWSER__ && context.prefixIdentifiers && keyProperty) {
+ // #2085 process :key expression needs to be processed in order for it
+ // to behave consistently for and .
+ // In the case of ``, the node is discarded and never
+ // traversed so its key expression won't be processed by the normal
+ // transforms.
+ keyProperty.value = processExpression(
+ keyProperty.value as SimpleExpressionNode,
+ context
+ )
+ }
+
const isStableFragment =
forNode.source.type === NodeTypes.SIMPLE_EXPRESSION &&
forNode.source.isConstant
@@ -108,14 +129,7 @@ export const transformFor = createStructuralDirectiveTransform(
isSlotOutlet(node.children[0])
? (node.children[0] as SlotOutletNode) // api-extractor somehow fails to infer this
: null
- const keyProperty = keyProp
- ? createObjectProperty(
- `key`,
- keyProp.type === NodeTypes.ATTRIBUTE
- ? createSimpleExpression(keyProp.value!.content, true)
- : keyProp.exp!
- )
- : null
+
if (slotOutlet) {
// or
childBlock = slotOutlet.codegenNode as RenderSlotCall