• 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);
            }
    
  • 相关阅读:
    【转载】uboot的工具mkimage使用方法
    u-boot-2010.3移植到Tiny6410问题总结
    【转载】 GNU GCC 选项说明
    【转载】GCC 预处理器选项
    用kermit通过串口往nandflash任意地址里烧写任何文件!
    自己写Tiny6410的Bootloader总结!
    ARM常用汇编指令介绍
    Ubuntu14.04和Tiny6410挂载NFS服务!
    Tiny 6410的Linux学习总结!
    Tiny6410下的第一个Linux驱动程序
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1730216.html
Copyright © 2020-2023  润新知