Bläddra i källkod

feat: support v-model dynamic type binding for v-bind="object"

close #7296
Evan You 8 år sedan
förälder
incheckning
41838c8e86

+ 13 - 2
src/platforms/web/compiler/modules/model.js

@@ -26,8 +26,19 @@ import {
 function preTransformNode (el: ASTElement, options: CompilerOptions) {
   if (el.tag === 'input') {
     const map = el.attrsMap
-    if (map['v-model'] && (map['v-bind:type'] || map[':type'])) {
-      const typeBinding: any = getBindingAttr(el, 'type')
+    if (!map['v-model']) {
+      return
+    }
+
+    let typeBinding
+    if (map[':type'] || map['v-bind:type']) {
+      typeBinding = getBindingAttr(el, 'type')
+    }
+    if (!typeBinding && map['v-bind']) {
+      typeBinding = `(${map['v-bind']}).type`
+    }
+
+    if (typeBinding) {
       const ifCondition = getAndRemoveAttr(el, 'v-if', true)
       const ifConditionExtra = ifCondition ? `&&(${ifCondition})` : ``
       const hasElse = getAndRemoveAttr(el, 'v-else', true) != null

+ 50 - 0
test/unit/features/directives/model-dynamic.spec.js

@@ -127,6 +127,56 @@ describe('Directive v-model dynamic input type', () => {
       expect(vm.data.text).toBe('foo')
     }).then(done)
   })
+
+  it('with v-bind', done => {
+    const vm = new Vue({
+      data: {
+        data: {
+          text: 'foo',
+          checkbox: true
+        },
+        inputs: [{ id: 'one', type: 'text' }, { id: 'two', type: 'checkbox' }]
+      },
+      template: `<div>
+        <input v-for="i in inputs" v-bind="i" v-model="data[i.type]">
+      </div>`
+    }).$mount()
+    document.body.appendChild(vm.$el)
+
+    let el1 = vm.$el.children[0]
+    expect(el1.id).toBe('one')
+    expect(el1.type).toBe('text')
+    expect(el1.value).toBe('foo')
+    el1.value = 'bar'
+    triggerEvent(el1, 'input')
+    expect(vm.data.text).toBe('bar')
+
+    let el2 = vm.$el.children[1]
+    expect(el2.id).toBe('two')
+    expect(el2.type).toBe('checkbox')
+    expect(el2.checked).toBe(true)
+    el2.click()
+    expect(vm.data.checkbox).toBe(false)
+
+    // now in reverse!
+    vm.inputs.reverse()
+    waitForUpdate(() => {
+      el1 = vm.$el.children[0]
+      expect(el1.id).toBe('two')
+      expect(el1.type).toBe('checkbox')
+      expect(el1.checked).toBe(false)
+      el1.click()
+      expect(vm.data.checkbox).toBe(true)
+
+      el2 = vm.$el.children[1]
+      expect(el2.id).toBe('one')
+      expect(el2.type).toBe('text')
+      expect(el2.value).toBe('bar')
+      el2.value = 'foo'
+      triggerEvent(el2, 'input')
+      expect(vm.data.text).toBe('foo')
+    }).then(done)
+  })
 })
 
 function assertInputWorks (vm, type, chain) {