瀏覽代碼

v-model for checkbox and radio

Evan You 11 年之前
父節點
當前提交
a849093d06

+ 6 - 26
src/compile/compile.js

@@ -462,32 +462,12 @@ function collectAttrDirective (el, name, value, options) {
         'in attribute bindings.'
       )
     } else {
-      value = tokens[0].value
-      var descriptors
-      if (
-        name === 'value' ||
-        name === 'selected' ||
-        name === 'checked'
-      ) {
-        // special input attributes are bound as v-model
-        descriptors = dirParser.parse(value)
-        // remove attribute so v-model uses vm data as
-        // initial value
-        el.removeAttribute(name)
-        return {
-          name: 'model',
-          def: options.directives.model,
-          descriptors: descriptors
-        }
-      } else {
-        // normal attribute.
-        value = name + ':' + value
-        descriptors = dirParser.parse(value)
-        return {
-          name: 'attr',
-          def: options.directives.attr,
-          descriptors: descriptors
-        }
+      value = name + ':' + tokens[0].value
+      return {
+        name: 'attr',
+        def: options.directives.attr,
+        descriptors: dirParser.parse(value),
+        oneTime: tokens[0].oneTime
       }
     }
   }

+ 2 - 0
src/directives/attr.js

@@ -6,6 +6,8 @@ var namespaces = {
 
 module.exports = {
 
+  priority: 850,
+
   bind: function () {
     var name = this.arg
     var colonIndex = name.indexOf(':')

+ 26 - 0
src/directives/model/checkbox.js

@@ -0,0 +1,26 @@
+var _ = require('../../util')
+
+module.exports = {
+
+  bind: function () {
+    var self = this
+    var el = this.el
+    this.listener = function () {
+      self.set(el.checked, true)
+    }
+    _.on(el, 'change', this.listener)
+    if (el.checked) {
+      // watcher is not set up yet
+      this.vm.$set(this.expression, el.checked)
+    }
+  },
+
+  update: function (value) {
+    this.el.checked = !!value
+  },
+
+  unbind: function () {
+    _.off(this.el, 'change', this.listener)
+  }
+
+}

+ 1 - 0
src/directives/model/index.js

@@ -28,6 +28,7 @@ module.exports = {
   bind: function () {
     var el = this.el
     var tag = el.tagName
+    var handler
     if (tag === 'INPUT') {
       handler = handlers[el.type] || handlers.text
     } else if (tag === 'SELECT') {

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

@@ -0,0 +1,27 @@
+var _ = require('../../util')
+
+module.exports = {
+
+  bind: function () {
+    var self = this
+    var el = this.el
+    this.listener = function () {
+      self.set(el.value, true)
+    }
+    _.on(el, 'change', this.listener)
+    if (el.checked) {
+      // watcher is not set up yet
+      this.vm.$set(this.expression, el.value)
+    }
+  },
+
+  update: function (value) {
+    /* jshint eqeqeq: false */
+    this.el.checked = value == this.el.value
+  },
+
+  unbind: function () {
+    _.off(this.el, 'change', this.listener)
+  }
+
+}

+ 14 - 25
src/directives/model/text.js

@@ -35,9 +35,8 @@ module.exports = {
     // the input with the filtered value.
     this.listener = function textInputListener () {
       if (cpLocked) return
-      try {
-        var cursorPos = el.selectionStart
-      } catch (e) {}
+      var cursorPos
+      try { cursorPos = el.selectionStart } catch (e) {}
       self.set(
         number
           ? _.toNumber(el.value)
@@ -52,11 +51,21 @@ module.exports = {
     _.on(el, this.event, this.listener)
     // IE9 doesn't fire input event on backspace/del/cut
     if (!lazy && _.isIE9) {
-      shimIE9(this)
+      this.onCut = function () {
+        _.nextTick(self.listener)
+      }
+      this.onDel = function (e) {
+        if (e.keyCode === 46 || e.keyCode === 8) {
+          self.listener()
+        }
+      }
+      _.on(el, 'cut', this.onCut)
+      _.on(el, 'keyup', this.onDel)
     }
     // set initial value if present
     if (el.value) {
-      this.set(el.value, true)
+      // watcher is not set up yet
+      this.vm.$set(this.expression, el.value)
     }
   },
 
@@ -75,24 +84,4 @@ module.exports = {
     }
   }
 
-}
-
-/**
- * IE9 doesn't fire input event on backspace/del/cut,
- * so we have to shim it by adding some additoinal listners.
- *
- * @param {Directive} dir
- */
-
-function shimIE9 (dir) {
-  dir.onCut = function () {
-    _.nextTick(dir.listener)
-  }
-  dir.onDel = function (e) {
-    if (e.keyCode === 46 || e.keyCode === 8) {
-      dir.listener()
-    }
-  }
-  _.on(el, 'cut', dir.onCut)
-  _.on(el, 'keyup', dir.onDel)
 }