码迷,mamicode.com
首页 > 其他好文 > 详细

事件委托

时间:2017-12-13 23:23:06      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:node   事件冒泡   pos   listen   msm   prot   nbsp   log   javascrip   

技术分享图片

事件冒泡

事件冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播。例如当用户点击了<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 之后就可以来实现我们的需求了:


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 来删除代理的事件;

 

 

 

事件委托

标签:node   事件冒泡   pos   listen   msm   prot   nbsp   log   javascrip   

原文地址:http://www.cnblogs.com/JhonFlame/p/8030509.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!