]
})
})
+
+ test('element v-for key expression prefixing', () => {
+ const {
+ node: { codegenNode }
+ } = parseWithForTransform(
+ '<div v-for="item in items" :key="itemKey(item)">test</div>',
+ { 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(
+ '<template v-for="item in items" :key="itemKey(item)">test</template>',
+ { 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', () => {
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 <template v-for> and <div v-for>.
+ // In the case of `<template v-for>`, 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
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) {
// <slot v-for="..."> or <template v-for="..."><slot/></template>
childBlock = slotOutlet.codegenNode as RenderSlotCall