Evan You 12 лет назад
Родитель
Сommit
835dd0ed99
2 измененных файлов с 67 добавлено и 19 удалено
  1. 29 19
      src/compiler.js
  2. 38 0
      test/unit/specs/misc.js

+ 29 - 19
src/compiler.js

@@ -727,29 +727,12 @@ CompilerProto.parseDeps = function () {
 }
 
 /**
- *  Add an event delegation listener
+ *  Add an event listener to the delegator
  *  listeners are instances of directives with `isFn:true`
  */
 CompilerProto.addListener = function (listener) {
     var event = listener.arg,
-        delegator = this.delegators[event]
-    if (!delegator) {
-        // initialize a delegator
-        delegator = this.delegators[event] = {
-            targets: [],
-            handler: function (e) {
-                var i = delegator.targets.length,
-                    target
-                while (i--) {
-                    target = delegator.targets[i]
-                    if (target.el.contains(e.target) && target.handler) {
-                        target.handler(e)
-                    }
-                }
-            }
-        }
-        this.el.addEventListener(event, delegator.handler)
-    }
+        delegator = this.delegators[event] || this.addDelegator(event)
     delegator.targets.push(listener)
 }
 
@@ -761,6 +744,33 @@ CompilerProto.removeListener = function (listener) {
     targets.splice(targets.indexOf(listener), 1)
 }
 
+/**
+ *  Add an event delegator
+ */
+CompilerProto.addDelegator = function (event) {
+    var delegator = this.delegators[event] = {
+        targets: [],
+        handler: function (e) {
+            var target,
+                i = delegator.targets.length,
+                stop = e.stopPropagation
+            // overwrite propagation control
+            e.stopPropagation = function () {
+                e.stopped = true
+                stop.call(e)
+            }
+            while (i--) {
+                target = delegator.targets[i]
+                if (!e.stopped && target.handler && target.el.contains(e.target)) {
+                    target.handler(e)
+                }
+            }
+        }
+    }
+    this.el.addEventListener(event, delegator.handler)
+    return delegator
+}
+
 /**
  *  Do a one-time eval of a string that potentially
  *  includes bindings. It accepts additional raw data

+ 38 - 0
test/unit/specs/misc.js

@@ -130,4 +130,42 @@ describe('Misc Features', function () {
         })
     })
 
+    describe('event delegation', function () {
+
+        var inCalled = 0,
+            outCalled = 0,
+            innerHandler = function () {}
+        var v = new Vue({
+            template: '<div v-on="click:out"><div class="inner" v-on="click:in"></div></div>',
+            methods: {
+                'in': function (e) {
+                    inCalled++
+                    innerHandler(e)
+                },
+                out: function () {
+                    outCalled++
+                }
+            }
+        })
+        v.$appendTo('#test')
+
+        it('should work', function () {
+            var e = mockMouseEvent('click')
+            v.$el.querySelector('.inner').dispatchEvent(e)
+            assert.strictEqual(inCalled, 1)
+            assert.strictEqual(outCalled, 1)
+        })
+        
+        it('should allow stopPropagation()', function () {
+            innerHandler = function (e) {
+                e.stopPropagation()
+            }
+            var e = mockMouseEvent('click')
+            v.$el.querySelector('.inner').dispatchEvent(e)
+            assert.strictEqual(inCalled, 2)
+            assert.strictEqual(outCalled, 1)
+        })
+
+    })
+
 })