]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(v-model): allow v-model usage on declared custom elements
authorEvan You <yyx990803@gmail.com>
Mon, 27 Jul 2020 21:09:21 +0000 (17:09 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 27 Jul 2020 21:09:30 +0000 (17:09 -0400)
fix #1699

packages/compiler-core/src/options.ts
packages/compiler-core/src/transform.ts
packages/compiler-dom/__tests__/transforms/__snapshots__/vModel.spec.ts.snap
packages/compiler-dom/__tests__/transforms/vModel.spec.ts
packages/compiler-dom/src/transforms/vModel.ts

index 52eb8fa8028030805885090bcc036dbf25d56f35..f0d5258ce635cfb807c023bce328543ac0b93afa 100644 (file)
@@ -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
index f93b617cbcfe475f512ce2c8303235c4d796c846..05284751ab3baf6e8aec3b3db7772bc70f89b443 100644 (file)
@@ -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,
index 67aaa19bffd4f1d317aea51c7425143a551bb118..83e505485782ca1dd771de3849e0b13901115994 100644 (file)
@@ -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
 
index acf9cb95b11660764c969bdaa294d45bd40dfd51..3da0b30085fedaa6e71026dbeba654fb98b9596b 100644 (file)
@@ -115,6 +115,17 @@ describe('compiler: transform v-model', () => {
       )
     })
 
+    test('should allow usage on custom element', () => {
+      const onError = jest.fn()
+      const root = transformWithModel('<my-input v-model="model" />', {
+        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(`<input type="file" v-model="test"/>`, {
index 693bfcceada7c5ef748f2ceaba139e9775d948e7..83984d23e73d2202e86c6f4ae88494c78fea7823 100644 (file)
@@ -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