diff --git a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap index 498c03d35c6..d647b073453 100644 --- a/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap +++ b/packages/compiler-core/__tests__/transforms/__snapshots__/vIf.spec.ts.snap @@ -105,3 +105,17 @@ return function render() { } }" `; + +exports[`compiler: v-if codegen v-if with key 1`] = ` +"const _Vue = Vue + +return function render() { + with (this) { + const { openBlock: _openBlock, createVNode: _createVNode, createBlock: _createBlock, createCommentVNode: _createCommentVNode } = _Vue + + return (_openBlock(), ok + ? _createBlock(\\"div\\", { key: \\"some-key\\" }) + : _createCommentVNode(\\"v-if\\", true)) + } +}" +`; diff --git a/packages/compiler-core/__tests__/transforms/vIf.spec.ts b/packages/compiler-core/__tests__/transforms/vIf.spec.ts index f50ad66297d..b6c2e86a28c 100644 --- a/packages/compiler-core/__tests__/transforms/vIf.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vIf.spec.ts @@ -530,6 +530,20 @@ describe('compiler: v-if', () => { ) }) + test('v-if with key', () => { + const { + root, + node: { codegenNode } + } = parseWithIfTransform(`
`) + const branch1 = (codegenNode.expressions[1] as ConditionalExpression) + .consequent as CallExpression + expect(branch1.arguments).toMatchObject([ + `"div"`, + createObjectMatcher({ key: 'some-key' }) + ]) + expect(generate(root).code).toMatchSnapshot() + }) + test.todo('with comments') }) }) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index 3060c1c1095..280e9c5e2dc 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -253,7 +253,18 @@ export function injectProp( } propsWithInjection = props } else if (props.type === NodeTypes.JS_OBJECT_EXPRESSION) { - props.properties.unshift(prop) + let alreadyExists = false + // check existing key to avoid overriding user provided keys + if (prop.key.type === NodeTypes.SIMPLE_EXPRESSION) { + const propKeyName = prop.key.content + alreadyExists = props.properties.some(p => ( + p.key.type === NodeTypes.SIMPLE_EXPRESSION && + p.key.content === propKeyName + )) + } + if (!alreadyExists) { + props.properties.unshift(prop) + } propsWithInjection = props } else { // single v-bind with expression, return a merged replacement