上次说到我们在无菌环境中设计了一个事件代理函数,但性能是个问题,解决它我们需要缓存节点集合,发现节点集合不足以应对新情况时,再替换这个节点集合,重新开始匹配。下面是新的方案:
var delegate = function(selector,type,callback){ |
addEvent(document,type,function(e){ |
var node = e.srcElement || e.target; |
for(var i=0,el;el = els[i++];){ |
return callback.call(node,e); |
for(var i=0,el;el = els[i++];){ |
return callback.call(node,e); |
好了,我们现在来考虑另一种情况。之前我们的判定都是用全等于来比较,但如果事件源是来自更底层的元素呢?换言之,是下面的情况。
< div onclick = "alert('outer')" id = "outer" > |
< div onclick = "alert('middle')" id = "middle" > |
< div onclick = "alert('inner')" id = "inner" ></ div > |
当我们点击inner元素时,它上面的middle与outer的onclick也触发,因此我们必须引入包含判定了。这里我直接给出答案,具体可见我的这一篇博文。
var contains = function (el, root) { |
if (el.compareDocumentPosition) |
return (el.compareDocumentPosition(root) & 8) === 8; |
if (root.contains && el.nodeType === 1){ |
return root.contains(el) && root !== el; |
while ((el = el.parentNode)) |
if (el === root) return true ; |
var delegate = function (selector,type,callback){ |
addEvent(document,type, function (e){ |
var src = e.srcElement || e.target; |
for ( var i=0,el;el = els[i++];){ |
if (el === src || contains(src,el) ){ |
return callback.call(el,e); |
for ( var i=0,el;el = els[i++];){ |
if (el === src || contains(src,el) ){ |
return callback.call(el,e); |
我们再把筛选事件源的逻辑独立出来,就变成下面这个样子。是时候考虑如第一部分设计的事件系统衔接起来了!
var handle = function (e,obj){ |
src = e.srcElement || e.target, |
for ( var i=0,el;el = els[i++];){ |
if (el === src || contains(src,el) ){ |
return obj.callback.call(el,e); |
els = obj.nodes = $(obj.selector); |
for ( var i=0,el;el = els[i++];){ |
if (el === src || contains(src,el) ){ |
return obj.callback.call(el,e); |
var delegate = function (selector,type,callback){ |
handleObj.callback = callback; |
handleObj.selector = selector; |
handleObj.nodes = $(selector); |
addEvent(document,type, function (e){ |