Răsfoiți Sursa

use Directive.on

Evan You 10 ani în urmă
părinte
comite
feab94f151

+ 40 - 17
src/directive.js

@@ -37,6 +37,7 @@ function Directive (name, el, vm, descriptor, def, host) {
   this._host = host
   this._locked = false
   this._bound = false
+  this._listeners = null
   // init
   this._bind(def)
 }
@@ -171,23 +172,6 @@ p._checkParam = function (name) {
   return param
 }
 
-/**
- * Teardown the watcher and call unbind.
- */
-
-p._teardown = function () {
-  if (this._bound) {
-    this._bound = false
-    if (this.unbind) {
-      this.unbind()
-    }
-    if (this._watcher) {
-      this._watcher.teardown()
-    }
-    this.vm = this.el = this._watcher = null
-  }
-}
-
 /**
  * Set the corresponding value with the setter.
  * This should only be used in two-way directives
@@ -227,4 +211,43 @@ p._withLock = function (fn) {
   })
 }
 
+/**
+ * Convenience method that attaches a DOM event listener
+ * to the directive element and autometically tears it down
+ * during unbind.
+ *
+ * @param {String} event
+ * @param {Function} handler
+ */
+
+p.on = function (event, handler) {
+  _.on(this.el, event, handler)
+  ;(this._listeners || (this._listeners = []))
+    .push([event, handler])
+}
+
+/**
+ * Teardown the watcher and call unbind.
+ */
+
+p._teardown = function () {
+  if (this._bound) {
+    this._bound = false
+    if (this.unbind) {
+      this.unbind()
+    }
+    if (this._watcher) {
+      this._watcher.teardown()
+    }
+    var listeners = this._listeners
+    if (listeners) {
+      for (var i = 0; i < listeners.length; i++) {
+        _.off(this.el, listeners[i][0], listeners[i][1])
+      }
+    }
+    this.vm = this.el =
+    this._watcher = this._listeners = null
+  }
+}
+
 module.exports = Directive

+ 11 - 19
src/directives/model/checkbox.js

@@ -1,5 +1,3 @@
-var _ = require('../../util')
-
 module.exports = {
 
   bind: function () {
@@ -8,6 +6,14 @@ module.exports = {
     var trueExp = this._checkParam('true-exp')
     var falseExp = this._checkParam('false-exp')
 
+    this._matchValue = function (value) {
+      var trueValue = true
+      if (trueExp !== null) {
+        trueValue = self.vm.$eval(trueExp)
+      }
+      return trueValue === value
+    }
+
     function getValue () {
       var val = el.checked
       if (val && trueExp !== null) {
@@ -18,21 +24,11 @@ module.exports = {
       }
       return val
     }
-    this._getValue = getValue
 
-    function matchValue (value) {
-      var trueValue = true
-      if (trueExp !== null) {
-        trueValue = self.vm.$eval(trueExp)
-      }
-      return trueValue === value
-    }
-    this._matchValue = matchValue
-
-    this.listener = function () {
+    this.on('change', function () {
       self.set(getValue())
-    }
-    _.on(el, 'change', this.listener)
+    })
+
     if (el.checked) {
       this._initValue = getValue()
     }
@@ -40,9 +36,5 @@ module.exports = {
 
   update: function (value) {
     this.el.checked = this._matchValue(value)
-  },
-
-  unbind: function () {
-    _.off(this.el, 'change', this.listener)
   }
 }

+ 9 - 12
src/directives/model/radio.js

@@ -7,7 +7,8 @@ module.exports = {
     var el = this.el
     var number = this._checkParam('number') != null
     var expression = this._checkParam('exp')
-    function getValue () {
+
+    this.getValue = function () {
       var val = el.value
       if (number) {
         val = _.toNumber(val)
@@ -16,23 +17,19 @@ module.exports = {
       }
       return val
     }
-    this._getValue = getValue
-    this.listener = function () {
-      self.set(getValue())
-    }
-    _.on(el, 'change', this.listener)
+
+    this.on('change', function () {
+      self.set(self.getValue())
+    })
+
     if (el.checked) {
-      this._initValue = getValue()
+      this._initValue = this.getValue()
     }
   },
 
   update: function (value) {
     /* eslint-disable eqeqeq */
-    this.el.checked = value == this._getValue()
+    this.el.checked = value == this.getValue()
     /* eslint-enable eqeqeq */
-  },
-
-  unbind: function () {
-    _.off(this.el, 'change', this.listener)
   }
 }

+ 2 - 5
src/directives/model/select.js

@@ -20,7 +20,7 @@ module.exports = {
     }
     this.number = this._checkParam('number') != null
     this.multiple = el.hasAttribute('multiple')
-    this.listener = function () {
+    this.on('change', function () {
       var value = self.multiple
         ? getMultiValue(el)
         : el.value
@@ -30,8 +30,7 @@ module.exports = {
           : _.toNumber(value)
         : value
       self.set(value)
-    }
-    _.on(el, 'change', this.listener)
+    })
     checkInitialValue.call(this)
     // All major browsers except Firefox resets
     // selectedIndex with value -1 to 0 when the element
@@ -64,13 +63,11 @@ module.exports = {
   },
 
   unbind: function () {
-    _.off(this.el, 'change', this.listener)
     this.vm.$off('hook:attached', this.forceUpdate)
     if (this.optionWatcher) {
       this.optionWatcher.teardown()
     }
   }
-
 }
 
 /**

+ 17 - 36
src/directives/model/text.js

@@ -24,33 +24,29 @@ module.exports = {
     // suggestions... (see Discussion/#162)
     var composing = false
     if (!_.isAndroid && !isRange) {
-      this.onComposeStart = function () {
+      this.on('compositionstart', function () {
         composing = true
-      }
-      this.onComposeEnd = function () {
+      })
+      this.on('compositionend', function () {
         composing = false
         // in IE11 the "compositionend" event fires AFTER
         // the "input" event, so the input handler is blocked
         // at the end... have to call it here.
         self.listener()
-      }
-      _.on(el, 'compositionstart', this.onComposeStart)
-      _.on(el, 'compositionend', this.onComposeEnd)
+      })
     }
 
     // prevent messing with the input when user is typing,
     // and force update on blur.
     this.focused = false
     if (!isRange) {
-      this.onFocus = function () {
+      this.on('focus', function () {
         self.focused = true
-      }
-      this.onBlur = function () {
+      })
+      this.on('blur', function () {
         self.focused = false
         self.listener()
-      }
-      _.on(el, 'focus', this.onFocus)
-      _.on(el, 'blur', this.onBlur)
+      })
     }
 
     // Now attach the main listener
@@ -63,7 +59,9 @@ module.exports = {
       // force update here, because the watcher may not
       // run when the value is the same.
       _.nextTick(function () {
-        self.update(self._watcher.value)
+        if (self._bound) {
+          self.update(self._watcher.value)
+        }
       })
     }
     if (debounce) {
@@ -87,24 +85,22 @@ module.exports = {
         jQuery(el).on('input', this.listener)
       }
     } else {
-      _.on(el, 'change', this.listener)
+      this.on('change', this.listener)
       if (!lazy) {
-        _.on(el, 'input', this.listener)
+        this.on('input', this.listener)
       }
     }
 
     // IE9 doesn't fire input event on backspace/del/cut
     if (!lazy && _.isIE9) {
-      this.onCut = function () {
+      this.on('cut', function () {
         _.nextTick(self.listener)
-      }
-      this.onDel = function (e) {
+      })
+      this.on('keyup', 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
@@ -129,21 +125,6 @@ module.exports = {
     if (this.hasjQuery) {
       jQuery(el).off('change', this.listener)
       jQuery(el).off('input', this.listener)
-    } else {
-      _.off(el, 'change', this.listener)
-      _.off(el, 'input', this.listener)
-    }
-    if (this.onComposeStart) {
-      _.off(el, 'compositionstart', this.onComposeStart)
-      _.off(el, 'compositionend', this.onComposeEnd)
-    }
-    if (this.onCut) {
-      _.off(el, 'cut', this.onCut)
-      _.off(el, 'keyup', this.onDel)
-    }
-    if (this.onFocus) {
-      _.off(el, 'focus', this.onFocus)
-      _.off(el, 'blur', this.onBlur)
     }
   }
 }

+ 1 - 2
src/directives/on.js

@@ -15,7 +15,7 @@ module.exports = {
       this.iframeBind = function () {
         _.on(self.el.contentWindow, self.arg, self.handler)
       }
-      _.on(this.el, 'load', this.iframeBind)
+      this.on('load', this.iframeBind)
     }
   },
 
@@ -55,6 +55,5 @@ module.exports = {
 
   unbind: function () {
     this.reset()
-    _.off(this.el, 'load', this.iframeBind)
   }
 }

+ 5 - 5
test/unit/specs/directives/model_spec.js

@@ -64,7 +64,7 @@ if (_.inBrowser) {
         expect(el.childNodes[0].checked).toBe(true)
         expect(el.childNodes[1].checked).toBe(false)
         expect(vm.test).toBe(1)
-        vm._directives[1].unbind()
+        vm._directives[1]._teardown()
         el.childNodes[1].click()
         expect(vm.test).toBe(1)
         done()
@@ -124,7 +124,7 @@ if (_.inBrowser) {
         el.firstChild.click()
         expect(el.firstChild.checked).toBe(true)
         expect(vm.test).toBe(true)
-        vm._directives[0].unbind()
+        vm._directives[0]._teardown()
         el.firstChild.click()
         expect(el.firstChild.checked).toBe(false)
         expect(vm.test).toBe(true)
@@ -471,7 +471,7 @@ if (_.inBrowser) {
         el.firstChild.value = 'c'
         trigger(el.firstChild, 'input')
         expect(vm.test).toBe('c')
-        vm._directives[0].unbind()
+        vm._directives[0]._teardown()
         el.firstChild.value = 'd'
         trigger(el.firstChild, 'input')
         expect(vm.test).toBe('c')
@@ -614,7 +614,7 @@ if (_.inBrowser) {
         })
         expect(vm.test).toBe('a')
         // teardown
-        vm._directives[0].unbind()
+        vm._directives[0]._teardown()
         input.value = 'bbb'
         trigger(input, 'keyup', function (e) {
           e.keyCode = 8
@@ -720,7 +720,7 @@ if (_.inBrowser) {
         el.firstChild.value = 'c'
         jQuery(el.firstChild).trigger('change')
         expect(vm.test).toBe('c')
-        vm._directives[0].unbind()
+        vm._directives[0]._teardown()
         el.firstChild.value = 'd'
         jQuery(el.firstChild).trigger('change')
         expect(vm.test).toBe('c')