Răsfoiți Sursa

event delegation in sd-each

Evan You 13 ani în urmă
părinte
comite
5227248740
3 a modificat fișierele cu 73 adăugiri și 10 ștergeri
  1. 3 0
      src/directive-parser.js
  2. 67 10
      src/directives.js
  3. 3 0
      src/seed.js

+ 3 - 0
src/directive-parser.js

@@ -24,6 +24,9 @@ function Directive (directiveName, expression) {
         }
     }
 
+    this.directiveName = directiveName
+    this.expression = expression
+
     var rawKey   = expression.match(KEY_RE)[0], // guarded in parse
         argMatch = rawKey.match(ARG_RE)
 

+ 67 - 10
src/directives.js

@@ -1,6 +1,29 @@
 var config = require('./config'),
     watchArray = require('./watch-array')
 
+// sniff matchesSelector() method name.
+
+var matches = 'atchesSelector',
+    prefixes = ['m', 'webkitM', 'mozM', 'msM']
+
+prefixes.some(function (prefix) {
+    var match = prefix + matches
+    if (document.body[match]) {
+        matches = match
+        return true
+    }
+})
+
+function delegateCheck (current, top, selector) {
+    if (current.webkitMatchesSelector(selector)) {
+        return current
+    } else if (current === top) {
+        return false
+    } else {
+        return delegateCheck(current.parentNode, top, selector)
+    }
+}
+
 module.exports = {
 
     text: function (value) {
@@ -41,14 +64,42 @@ module.exports = {
 
     on: {
         fn : true,
+        bind: function (handler) {
+            if (this.seed.each) {
+                this.selector = '[' + this.directiveName + '*="' + this.expression + '"]'
+                this.delegator = this.seed.el.parentNode
+            }
+        },
         update: function (handler) {
+            this.unbind()
+            if (!handler) return
             var self  = this,
-                event = this.arg
-            if (this.handler) {
-                this.el.removeEventListener(event, this.handler)
-            }
-            if (handler) {
-                var proxy = function (e) {
+                event = this.arg,
+                selector  = this.selector,
+                delegator = this.delegator
+            if (delegator) {
+
+                // for each blocks, delegate for better performance
+                if (!delegator[selector]) {
+                    console.log('binding listener')
+                    delegator[selector] = function (e) {
+                        var target = delegateCheck(e.target, delegator, selector)
+                        if (target) {
+                            handler({
+                                el            : target,
+                                originalEvent : e,
+                                directive     : self,
+                                seed          : target.seed
+                            })
+                        }
+                    }
+                    delegator.addEventListener(event, delegator[selector])
+                }
+
+            } else {
+
+                // a normal handler
+                this.handler = function (e) {
                     handler({
                         el            : e.currentTarget,
                         originalEvent : e,
@@ -56,13 +107,18 @@ module.exports = {
                         seed          : self.seed
                     })
                 }
-                this.el.addEventListener(event, proxy)
-                this.handler = proxy
+                this.el.addEventListener(event, this.handler)
+
             }
         },
         unbind: function () {
-            var event = this.arg
-            if (this.handlers) {
+            var event = this.arg,
+                selector  = this.selector,
+                delegator = this.delegator
+            if (delegator && delegator[selector]) {
+                delegator.removeEventListener(event, delegator[selector])
+                delete delegator[selector]
+            } else if (this.handler) {
                 this.el.removeEventListener(event, this.handler)
             }
         }
@@ -91,6 +147,7 @@ module.exports = {
             var Seed = require('./seed'),
                 node = this.el.cloneNode(true)
             var spore = new Seed(node, {
+                    each: true,
                     eachPrefixRE: new RegExp('^' + this.arg + '.'),
                     parentSeed: this.seed,
                     index: index,

+ 3 - 0
src/seed.js

@@ -14,6 +14,7 @@ function Seed (el, options) {
     }
 
     this.el         = el
+    el.seed         = this
     this._bindings  = {}
 
     // copy options
@@ -74,6 +75,7 @@ Seed.prototype._compileNode = function (node, root) {
 
             var id = node.id,
                 seed = new Seed(node, {
+                    child: true,
                     parentSeed: self
                 })
             if (id) {
@@ -206,6 +208,7 @@ Seed.prototype._unbind = function () {
 
 Seed.prototype._destroy = function () {
     this._unbind()
+    delete this.el.seed
     this.el.parentNode.removeChild(this.el)
     if (this.parentSeed && this.id) {
         delete this.parentSeed['$' + this.id]