javascript 跨浏览器的事件系统4

上次说到我们在无菌环境中设计了一个事件代理函数,但性能是个问题,解决它我们需要缓存节点集合,发现节点集合不足以应对新情况时,再替换这个节点集合,重新开始匹配。下面是新的方案:

 

        var delegate = function(selector,type,callback){

          var els = $(selector);

          addEvent(document,type,function(e){

            var flag = true;

            var node = e.srcElement || e.target;

            for(var i=0,el;el = els[i++];){

              if(node === el){

                flag = false;

                return callback.call(node,e);

              }

            }

            if(flag){

              els = $(selector);

              for(var i=0,el;el = els[i++];){

                if(node === el){

                  return callback.call(node,e);

                }

              }

            }

          },true);

        }

好了,我们现在来考虑另一种情况。之前我们的判定都是用全等于来比较,但如果事件源是来自更底层的元素呢?换言之,是下面的情况。

 

    <div onclick="alert('outer')" id="outer">

      <div onclick="alert('middle')" id="middle">

        <div onclick="alert('inner')" id="inner"></div>

      </div>

    </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;

        return false;

      }

      var delegate = function(selector,type,callback){

        var els = $(selector);

        addEvent(document,type,function(e){

          var flag = true;

          var src = e.srcElement || e.target;

          for(var i=0,el;el = els[i++];){

            if(el === src || contains(src,el) ){

              flag = false;

              return callback.call(el,e);

            }

          }

          if(flag){

            els = $(selector);

            for(var i=0,el;el = els[i++];){

              if(el === src || contains(src,el) ){

                return callback.call(el,e);

              }

            }

          }

        },true);

      }

我们再把筛选事件源的逻辑独立出来,就变成下面这个样子。是时候考虑如第一部分设计的事件系统衔接起来了!

 

        var handle = function(e,obj){

          var flag = true, 

          src = e.srcElement || e.target,

          els = obj.nodes;

          for(var i=0,el;el = els[i++];){

            if(el === src || contains(src,el) ){

              flag = false;

              return obj.callback.call(el,e);

            }

          }

          if(flag){

            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){

          var handleObj = {};

          handleObj.callback = callback;

          handleObj.selector = selector;

          handleObj.nodes = $(selector);

          addEvent(document,type,function(e){

            handle(e,handleObj)

          },true);

        }

你可能感兴趣的:(JavaScript)