From 1f2de9e232409b09c97b67d0824d1450beed6eb1 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 5 Feb 2020 15:21:47 -0500 Subject: [PATCH] fix(v-model): should use dynamic directive on input with dynamic v-bind --- packages/compiler-core/src/utils.ts | 11 ++++++ .../__snapshots__/vModel.spec.ts.snap | 37 +++++++++++++++++++ .../__tests__/transforms/vModel.spec.ts | 13 +++++++ .../compiler-dom/src/transforms/vModel.ts | 7 +++- .../src/transforms/ssrTransformElement.ts | 12 ++---- .../compiler-ssr/src/transforms/ssrVModel.ts | 3 +- 6 files changed, 72 insertions(+), 11 deletions(-) diff --git a/packages/compiler-core/src/utils.ts b/packages/compiler-core/src/utils.ts index 78e952e4..d160e96e 100644 --- a/packages/compiler-core/src/utils.ts +++ b/packages/compiler-core/src/utils.ts @@ -205,6 +205,17 @@ export function findProp( } } +export function hasDynamicKeyVBind(node: ElementNode): boolean { + return node.props.some( + p => + p.type === NodeTypes.DIRECTIVE && + p.name === 'bind' && + (!p.arg || // v-bind="obj" + p.arg.type !== NodeTypes.SIMPLE_EXPRESSION || // v-bind:[_ctx.foo] + !p.arg.isStatic) // v-bind:[foo] + ) +} + export function createBlockExpression( blockExp: BlockCodegenNode, context: TransformContext diff --git a/packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap b/packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap index f996e955..88bba3b0 100644 --- a/packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap +++ b/packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap @@ -1,5 +1,42 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`compiler: transform v-model input w/ dynamic v-bind 1`] = ` +"const _Vue = Vue + +return function render() { + with (this) { + const { vModelDynamic: _vModelDynamic, mergeProps: _mergeProps, createVNode: _createVNode, withDirectives: _withDirectives, createBlock: _createBlock, openBlock: _openBlock } = _Vue + + return (_openBlock(), _withDirectives(_createBlock(\\"input\\", _mergeProps(obj, { + modelValue: model, + \\"onUpdate:modelValue\\": $event => (model = $event) + }), null, 16 /* FULL_PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]), [ + [_vModelDynamic, model] + ])) + } +}" +`; + +exports[`compiler: transform v-model input w/ dynamic v-bind 2`] = ` +"const _Vue = Vue + +return function render() { + with (this) { + const { vModelDynamic: _vModelDynamic, createVNode: _createVNode, withDirectives: _withDirectives, resolveDirective: _resolveDirective, createBlock: _createBlock, openBlock: _openBlock } = _Vue + + const _directive_bind = _resolveDirective(\\"bind\\") + + return (_openBlock(), _withDirectives(_createBlock(\\"input\\", { + modelValue: model, + \\"onUpdate:modelValue\\": $event => (model = $event) + }, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]), [ + [_directive_bind, val, key], + [_vModelDynamic, model] + ])) + } +}" +`; + exports[`compiler: transform v-model modifiers .lazy 1`] = ` "const _Vue = Vue diff --git a/packages/compiler-dom/__tests__/transforms/vModel.spec.ts b/packages/compiler-dom/__tests__/transforms/vModel.spec.ts index a70e117a..acf9cb95 100644 --- a/packages/compiler-dom/__tests__/transforms/vModel.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vModel.spec.ts @@ -63,6 +63,19 @@ describe('compiler: transform v-model', () => { expect(generate(root).code).toMatchSnapshot() }) + test('input w/ dynamic v-bind', () => { + const root = transformWithModel('') + + expect(root.helpers).toContain(V_MODEL_DYNAMIC) + expect(generate(root).code).toMatchSnapshot() + + const root2 = transformWithModel( + '' + ) + expect(root2.helpers).toContain(V_MODEL_DYNAMIC) + expect(generate(root2).code).toMatchSnapshot() + }) + test('simple expression for select', () => { const root = transformWithModel('