From: Evan You Date: Mon, 27 Jul 2020 21:09:21 +0000 (-0400) Subject: fix(v-model): allow v-model usage on declared custom elements X-Git-Tag: v3.0.0-rc.5~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71c3c6e2a03095ddd4c2a1e15957afd3ec8d4120;p=thirdparty%2Fvuejs%2Fcore.git fix(v-model): allow v-model usage on declared custom elements fix #1699 --- diff --git a/packages/compiler-core/src/options.ts b/packages/compiler-core/src/options.ts index 52eb8fa802..f0d5258ce6 100644 --- a/packages/compiler-core/src/options.ts +++ b/packages/compiler-core/src/options.ts @@ -28,7 +28,7 @@ export interface ParserOptions { /** * Separate option for end users to extend the native elements list */ - isCustomElement?: (tag: string) => boolean + isCustomElement?: (tag: string) => boolean | void /** * Get tag namespace */ @@ -83,6 +83,10 @@ export interface TransformOptions { * for them. */ isBuiltInComponent?: (tag: string) => symbol | void + /** + * Used by some transforms that expects only native elements + */ + isCustomElement?: (tag: string) => boolean | void /** * Transform expressions like {{ foo }} to `_ctx.foo`. * If this option is false, the generated code will be wrapped in a diff --git a/packages/compiler-core/src/transform.ts b/packages/compiler-core/src/transform.ts index f93b617cbc..05284751ab 100644 --- a/packages/compiler-core/src/transform.ts +++ b/packages/compiler-core/src/transform.ts @@ -117,6 +117,7 @@ export function createTransformContext( directiveTransforms = {}, transformHoist = null, isBuiltInComponent = NOOP, + isCustomElement = NOOP, expressionPlugins = [], scopeId = null, ssr = false, @@ -134,6 +135,7 @@ export function createTransformContext( directiveTransforms, transformHoist, isBuiltInComponent, + isCustomElement, expressionPlugins, scopeId, ssr, 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 67aaa19bff..83e5054857 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,21 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`compiler: transform v-model errors should allow custom element 1`] = ` +"const _Vue = Vue + +return function render(_ctx, _cache) { + with (_ctx) { + const { vModelText: _vModelText, createVNode: _createVNode, withDirectives: _withDirectives, openBlock: _openBlock, createBlock: _createBlock } = _Vue + + return _withDirectives((_openBlock(), _createBlock(\\"my-input\\", { + \\"onUpdate:modelValue\\": $event => (model = $event) + }, null, 8 /* PROPS */, [\\"onUpdate:modelValue\\"])), [ + [_vModelText, model] + ]) + } +}" +`; + exports[`compiler: transform v-model input w/ dynamic v-bind 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 acf9cb95b1..3da0b30085 100644 --- a/packages/compiler-dom/__tests__/transforms/vModel.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vModel.spec.ts @@ -115,6 +115,17 @@ describe('compiler: transform v-model', () => { ) }) + test('should allow usage on custom element', () => { + const onError = jest.fn() + const root = transformWithModel('', { + onError, + isCustomElement: tag => tag.startsWith('my-') + }) + expect(root.helpers).toContain(V_MODEL_TEXT) + expect(onError).not.toHaveBeenCalled() + expect(generate(root).code).toMatchSnapshot() + }) + test('should raise error if used file input element', () => { const onError = jest.fn() transformWithModel(``, { diff --git a/packages/compiler-dom/src/transforms/vModel.ts b/packages/compiler-dom/src/transforms/vModel.ts index 693bfccead..83984d23e7 100644 --- a/packages/compiler-dom/src/transforms/vModel.ts +++ b/packages/compiler-dom/src/transforms/vModel.ts @@ -44,7 +44,12 @@ export const transformModel: DirectiveTransform = (dir, node, context) => { } const { tag } = node - if (tag === 'input' || tag === 'textarea' || tag === 'select') { + if ( + tag === 'input' || + tag === 'textarea' || + tag === 'select' || + context.isCustomElement(tag) + ) { let directiveToUse = V_MODEL_TEXT let isInvalidType = false if (tag === 'input') { @@ -86,7 +91,9 @@ export const transformModel: DirectiveTransform = (dir, node, context) => { } } else if (tag === 'select') { directiveToUse = V_MODEL_SELECT - } else if (tag === 'textarea') { + } + { + // textarea or custom elements __DEV__ && checkDuplicatedValue() } // inject runtime directive