zoukankan      html  css  js  c++  java
  • 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);
    }
    Top
    收藏
    关注
    评论
  • 相关阅读:
    推荐:俞敏洪的一分钟励志演讲
    信息系统开发平台OpenExpressApp - 内置支持的列表编辑方式
    WPF - 资源收集
    开源 - 开源协议
    信息系统开发平台OpenExpressApp - 总体架构的由来
    WPF - DataGrid 相关收集
    报表引擎 -架构描述
    推荐:图标编辑器
    Scrum之 回顾会议
    从买房来看软件有哪几个主要关注点
  • 原文地址:https://www.cnblogs.com/judypol/p/1730784.html
Copyright © 2011-2022 走看看