Evan You преди 10 години
родител
ревизия
1914dfe4dd
променени са 2 файла, в които са добавени 81 реда и са изтрити 2 реда
  1. 11 2
      src/platforms/web/compiler/directives/model.js
  2. 70 0
      test/unit/features/directives/model-radio.spec.js

+ 11 - 2
src/platforms/web/compiler/directives/model.js

@@ -21,7 +21,7 @@ export default function model (
         genCheckboxModel(el, value)
         break
       case 'radio':
-        genRadioModel(el, value)
+        genRadioModel(el, value, warn)
         break
       default:
         return genDefaultModel(el, value, modifiers, warn)
@@ -49,7 +49,16 @@ function genCheckboxModel (el: ASTElement, value: ?string) {
   )
 }
 
-function genRadioModel (el: ASTElement, value: ?string) {
+function genRadioModel (el: ASTElement, value: ?string, warn: Function) {
+  if (process.env.NODE_ENV !== 'production') {
+    if (el.attrsMap.checked != null) {
+      warn(
+        `<${el.tag} v-model="${value}" checked>:\n` +
+        `inline checked attributes will be ignored when using v-model. ` +
+        'Declare initial values in the component\'s data option instead.'
+      )
+    }
+  }
   const valueBinding = getBindingAttr(el, 'value')
   addProp(el, 'checked', `(${value}==${valueBinding})`)
   addHandler(el, 'change', `${value}=${valueBinding}`)

+ 70 - 0
test/unit/features/directives/model-radio.spec.js

@@ -0,0 +1,70 @@
+import Vue from 'vue'
+
+describe('Directive v-model radio', () => {
+  it('should work', done => {
+    const vm = new Vue({
+      data: {
+        test: '1'
+      },
+      template: `
+        <div>
+          <input type="radio" value="1" v-model="test" name="test">
+          <input type="radio" value="2" v-model="test" name="test">
+        </div>
+      `
+    }).$mount()
+    document.body.appendChild(vm.$el)
+    expect(vm.$el.childNodes[0].checked).toBe(true)
+    expect(vm.$el.childNodes[1].checked).toBe(false)
+    vm.test = '2'
+    waitForUpdate(() => {
+      expect(vm.$el.childNodes[0].checked).toBe(false)
+      expect(vm.$el.childNodes[1].checked).toBe(true)
+      vm.$el.childNodes[0].click()
+      expect(vm.$el.childNodes[0].checked).toBe(true)
+      expect(vm.$el.childNodes[1].checked).toBe(false)
+      expect(vm.test).toBe('1')
+    }).then(() => {
+      document.body.removeChild(vm.$el)
+    }).then(done)
+  })
+
+  it('should respect value bindings', done => {
+    const vm = new Vue({
+      data: {
+        test: 1
+      },
+      template: `
+        <div>
+          <input type="radio" :value="1" v-model="test" name="test">
+          <input type="radio" :value="2" v-model="test" name="test">
+        </div>
+      `
+    }).$mount()
+    document.body.appendChild(vm.$el)
+    expect(vm.$el.childNodes[0].checked).toBe(true)
+    expect(vm.$el.childNodes[1].checked).toBe(false)
+    vm.test = 2
+    waitForUpdate(() => {
+      expect(vm.$el.childNodes[0].checked).toBe(false)
+      expect(vm.$el.childNodes[1].checked).toBe(true)
+      vm.$el.childNodes[0].click()
+      expect(vm.$el.childNodes[0].checked).toBe(true)
+      expect(vm.$el.childNodes[1].checked).toBe(false)
+      expect(vm.test).toBe(1)
+    }).then(() => {
+      document.body.removeChild(vm.$el)
+    }).then(done)
+  })
+
+  it('warn inline checked', () => {
+    const vm = new Vue({
+      template: `<input v-model="test" type="radio" value="1" checked>`,
+      data: {
+        test: '2'
+      }
+    }).$mount()
+    expect(vm.$el.checked).toBe(false)
+    expect('inline checked attributes will be ignored when using v-model').toHaveBeenWarned()
+  })
+})