zoukankan      html  css  js  c++  java
  • 事件委托

    事件冒泡

    事件冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。例如当用户点击了<div>元素,click事件将按照<div>—><body>—><html>—>document的顺序进行传播。若在<div>和<body>上都定义了click事件,则在冒泡过程中会依次触发事件。如下:

    <script type="text/javascript">
            var div=document.getElementById("myDiv");
            div.onclick=function(event){
                alert("div");
            };
            document.body.onclick=function(event){
                alert("body");
            };    
    </script>

    点击<div>,将先输出“div”,再输出“body”。

    IE9,chrome,Firefox,Opera,Safari都支持事件冒泡,并将事件冒泡到window对象。


    事件捕获

    事件捕获是先由最上一级的节点先接收事件,然后向下传播到具体的节点。当用户点击了<div>元素,采用事件捕获,则click事件将按照document—><html>—><body>—><div>的顺序进行传播。

    若在<div>和<body>上都定义了click事件,如下:

    <script type="text/javascript">
            var div=document.getElementById("myDiv");    
            div.addEventListener("click",function(event){
                alert("div");
            },true);
            document.body.addEventListener("click",function(event){
                alert("body");
            },true);
            
        </script>

    点击<div>,将先输出“body”,再输出“div”。

    IE9,chrome,Firefox,Opera,Safari都支持事件捕获,但是IE8和IE8以下的版本只支持事件冒泡。尽管DOM2规范要求事件应该从document对象开始传播,但是现在的浏览器实现都是从window对象开始捕获事件。


    DOM事件流:

    结合上述,兼备捕获和冒泡,先捕获后冒泡。


    事件委托

    一般来讲,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,当事件响应到需要绑定的元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数。

     如下html,如果不用事件委托,将每一个li都去添加click事件监听,非常麻烦。如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,效率上需要消耗很多性能; 另外就是如果通过js动态创建的子节点,需要重新绑定事件。 而利用事件委托的话,只需要给父级绑定一个事件监听,即可让每个li都绑定上相应的事件。
    <ul id="line">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
            <!--不定数个li-->
        <li></li>
        <li></li>
    </ul>

    若要实现点击li标签,对应的li就会消失,只需把事件绑定在ul上,代码如下,

     //找到父元素,添加监听器
    document.getElementById("line").addEventListener("click",function (ev) {
            // ev.target是被点击元素
           // 如果被点击的是li元素
            if(ev.target&&ev.target.nodeName=="LI")
            {
                ev.target.remove();
            }
        })        
    在上述代码中, target 元素则是在 #line 元素之下具体被点击的元素,然后通过判断 target 的一些属性(比如:nodeName,id 等等)可以更精确地匹配到某一类 #list li 元素之上;
    对于复杂的匹配,如上方法则需要多个判定条件,显得很不灵活。此时可以通过使用 Element.matches API来精确匹配。
    Element.matches API 的基本使用方法: Element.matches(selectorString),selectorString 是个css选择器字符串.举个例子,ev.target.matches('li.li1')。如果 target 元素是标签 li 并且它的类是 li1 ,那么就会返回 true,否则返回 false;
     

    当然它的兼容性还有一些问题,需要 IE9 及以上的现代化浏览器版本;

    我们可以使用 Polyfill 来解决兼容性上的问题:

    if (!Element.prototype.matches) {
        Element.prototype.matches = 
            Element.prototype.matchesSelector || 
            Element.prototype.mozMatchesSelector ||
            Element.prototype.msMatchesSelector || 
            Element.prototype.oMatchesSelector || 
            Element.prototype.webkitMatchesSelector ||
            function(s) {
                var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                    i = matches.length;
                while (--i >= 0 && matches.item(i) !== this) {}
                return i > -1;            
            };
    }

    加上 Element.matches 之后就可以来实现我们的需求了:


    target和currentTarget的区别

    在冒泡模型里,e.currentTarget指的是注册了事件监听器的对象,而e.target指的是该对象里的子对象,例如点击上述例子中li标签,target指向li标签,而currentTarget则指向有监听器的ul标签。

    现在,假如li标签里面还包含着<span>之类的标签,而我们点击了<span>标签,此时target指向了<span>,并不是我们所想要的目标元素,故应该加个函数来寻找我们要的元素,代码如下

       while (target !== currentTarget) {  //判断是否到了遍历到了父层
            if (target.matches(targetSelector)) {// 判断是否匹配到我们所需要的元素
                var sTarget = target;
                // 执行绑定的函数,注意 this
               Function~~~
            }
    
            target = target.parentNode;//若不为所需元素,则将target指向其上一级元素
        }

     


     

    jQuery 中的事件委托

    jQuery 中的事件委托相信很多人都用过,它主要这几种方法来实现:

      • $.on: 基本用法: $('.parent').on('click', 'a', function () { console.log('click event on tag a'); }),它是 .parent 元素之下的 a 元素的事件代理到 $('.parent') 之上,只要在这个元素上有点击事件,就会自动寻找到 .parent 元素下的 a 元素,然后响应事件;
      • $.delegate: 基本用法: $('.parent').delegate('a', 'click', function () { console.log('click event on tag a'); }),同上,并且还有相对应的 $.delegate 来删除代理的事件;

  • 相关阅读:
    还有为window.close()方法弹出的询问窗口烦?
    ValidateTextBox发布绝对实用
    面向对象设计的11个原则
    关于建立控件、组件开发团队,有兴趣的网友请留言
    存储过程和触发器要使用链接服务器时要注意的一点
    “这块布的艺术成分都几高唧!”“有几高啊?”“三、四层楼那么高啦。”
    有没有人用过负离子发生器?
    摇滚你的页面。Free:RockUControl控件发布,开源:RevealTransitionImage
    控件开发团队序言及加入说明
    一些平时能用到的CSS效果(ZT+YC)
  • 原文地址:https://www.cnblogs.com/JhonFlame/p/8030509.html
Copyright © 2011-2022 走看看