Procházet zdrojové kódy

fix v-model warning on component (#3102)

kazuya kawaguchi před 9 roky
rodič
revize
cf1a697710

+ 3 - 1
src/platforms/web/runtime/directives/model.js

@@ -6,6 +6,8 @@
 import { warn } from 'core/util/index'
 import { isAndroid, isIE9 } from 'web/util/index'
 
+const modelableTagRE = /^input|select|textarea|vue-component-[0-9]+(-[0-9a-zA-Z_\-]*)?$/
+
 /* istanbul ignore if */
 if (isIE9) {
   // http://www.matts411.com/post/internet-explorer-9-oninput/
@@ -20,7 +22,7 @@ if (isIE9) {
 export default {
   bind (el, binding, vnode) {
     if (process.env.NODE_ENV !== 'production') {
-      if (!/input|select|textarea/.test(vnode.tag)) {
+      if (!modelableTagRE.test(vnode.tag)) {
         warn(
           `v-model is not supported on element type: <${vnode.tag}>. ` +
           'If you are working with contenteditable, it\'s recommended to ' +

+ 49 - 0
test/unit/features/directives/model-component.spec.js

@@ -0,0 +1,49 @@
+import Vue from 'vue'
+
+describe('Directive v-model component', () => {
+  it('should work', done => {
+    const vm = new Vue({
+      data: {
+        msg: 'hello'
+      },
+      template: `
+        <div>
+          <p>{{ msg }}</p>
+          <validate v-model="msg">
+            <input type="text">
+          </validate>
+        </div>
+      `,
+      components: {
+        validate: {
+          template: '<div><slot></slot></div>',
+          props: ['value'],
+          methods: {
+            onInput (e) {
+              // something validate ...
+              this.$emit('input', e)
+            }
+          },
+          mounted () {
+            this.$el.addEventListener('input', this.onInput)
+          },
+          destroyed () {
+            this.$el.removeEventListener('input', this.onInput)
+          }
+        }
+      }
+    }).$mount()
+    document.body.appendChild(vm.$el)
+    waitForUpdate(() => {
+      expect('v-model is not supported on element type').not.toHaveBeenWarned()
+      const input = vm.$el.querySelector('input')
+      input.value = 'world'
+      triggerEvent(input, 'input')
+    }).then(() => {
+      expect(vm.msg).toBe('world')
+    }).then(() => {
+      document.body.removeChild(vm.$el)
+      vm.$destroy()
+    }).then(done)
+  })
+})