Sfoglia il codice sorgente

new syntax for v-model object value bindings

Evan You 10 anni fa
parent
commit
f9ff579d28

+ 7 - 0
src/deprecations.js

@@ -186,6 +186,13 @@ if (process.env.NODE_ENV !== 'production') {
         'handler explicitly returns true. See https://github.com/yyx990803/vue/issues/1175 ' +
         'for more details.'
       )
+    },
+
+    MODEL_EXP: function (exp) {
+      warn(
+        'Params "exp", "true-exp" and "false-exp" for v-model will be deprecated in 1.0.0. ' +
+        'Use "bind-value", "bind-true-value" and "bind-false-value" instead.'
+      )
     }
 
   }

+ 16 - 0
src/directives/attr.js

@@ -1,12 +1,23 @@
 // xlink
 var xlinkNS = 'http://www.w3.org/1999/xlink'
 var xlinkRE = /^xlink:/
+
+// these input element attributes should also set their
+// corresponding properties
 var inputProps = {
   value: 1,
   checked: 1,
   selected: 1
 }
 
+// these attributes should set a hidden property for
+// binding v-model to object values
+var modelProps = {
+  value: '_value',
+  'true-value': '_trueValue',
+  'false-value': '_falseValue'
+}
+
 module.exports = {
 
   priority: 850,
@@ -56,5 +67,10 @@ module.exports = {
     } else {
       this.el.removeAttribute(attr)
     }
+    // set model props
+    var modelProp = modelProps[attr]
+    if (modelProp) {
+      this.el[modelProp] = value
+    }
   }
 }

+ 13 - 1
src/directives/model/checkbox.js

@@ -9,8 +9,14 @@ module.exports = {
     var falseExp = this.param('false-exp')
     var scope = this._scope || this.vm
 
+    if (process.env.NODE_ENV !== 'production' && (trueExp || falseExp)) {
+      _.deprecation.MODEL_EXP(this.expression)
+    }
+
     this._matchValue = function (value) {
-      if (trueExp !== null) {
+      if (el.hasOwnProperty('_trueValue')) {
+        return _.looseEqual(value, el._trueValue)
+      } else if (trueExp !== null) {
         return _.looseEqual(value, scope.$eval(trueExp))
       } else {
         return !!value
@@ -19,6 +25,12 @@ module.exports = {
 
     function getValue () {
       var val = el.checked
+      if (val && el.hasOwnProperty('_trueValue')) {
+        return el._trueValue
+      }
+      if (!val && el.hasOwnProperty('_falseValue')) {
+        return el._falseValue
+      }
       if (val && trueExp !== null) {
         val = scope.$eval(trueExp)
       }

+ 8 - 0
src/directives/model/radio.js

@@ -9,7 +9,15 @@ module.exports = {
     var expression = this.param('exp')
     var scope = this._scope || this.vm
 
+    if (process.env.NODE_ENV !== 'production' && expression) {
+      _.deprecation.MODEL_EXP(this.expression)
+    }
+
     this.getValue = function () {
+      // value overwrite via bind-value
+      if (el.hasOwnProperty('_value')) {
+        return el._value
+      }
       var val = el.value
       if (number) {
         val = _.toNumber(val)

+ 54 - 0
test/unit/specs/directives/model_spec.js

@@ -108,6 +108,34 @@ if (_.inBrowser) {
       })
     })
 
+    it('radio expression (new syntax)', function (done) {
+      var vm = new Vue({
+        el: el,
+        data: {
+          test: false,
+          test2: 'string1',
+          expression1: 'string1',
+          expression2: 'string2'
+        },
+        template:
+          '<input type="radio" value="1" v-model="test" name="test" bind-value="true">' +
+          '<input type="radio" value="0" v-model="test" name="test" bind-value="false">' +
+          '<input type="radio" value="1" v-model="test2" name="test2" bind-value="expression1">' +
+          '<input type="radio" value="0" v-model="test2" name="test2" bind-value="expression2">'
+      })
+      expect(el.childNodes[0].checked).toBe(false)
+      expect(el.childNodes[1].checked).toBe(true)
+      expect(el.childNodes[2].checked).toBe(true)
+      expect(el.childNodes[3].checked).toBe(false)
+      _.nextTick(function () {
+        el.childNodes[0].click()
+        expect(vm.test).toBe(true)
+        el.childNodes[3].click()
+        expect(vm.test2).toBe('string2')
+        done()
+      })
+    })
+
     it('checkbox', function (done) {
       var vm = new Vue({
         el: el,
@@ -167,6 +195,32 @@ if (_.inBrowser) {
       })
     })
 
+    it('checkbox expression (new syntax)', function (done) {
+      var vm = new Vue({
+        el: el,
+        data: {
+          test: '',
+          expression1: 'aTrueValue',
+          expression2: 'aFalseValue'
+        },
+        template: '<input type="checkbox" v-model="test" bind-true-value="expression1" bind-false-value="expression2">'
+      })
+      expect(vm.test).toBe('')
+      el.firstChild.click()
+      expect(vm.test).toBe('aTrueValue')
+      expect(el.firstChild.checked).toBe(true)
+      el.firstChild.click()
+      expect(vm.test).toBe('aFalseValue')
+      expect(el.firstChild.checked).toBe(false)
+      _.nextTick(function () {
+        vm.test = 'aTrueValue'
+        _.nextTick(function () {
+          expect(el.firstChild.checked).toBe(true)
+          done()
+        })
+      })
+    })
+
     it('select', function (done) {
       var vm = new Vue({
         el: el,