事件委托(事件代理)

利用冒泡的原理,将子元素的事件绑定到父元素上。

捕获和冒泡过程图

捕获:由window从上到下,到事件触发元素

冒泡:由事件触发元素到从下到上,到window

 

addEventListener的第三个参数为false(默认值),则页面是在冒泡阶段处理绑定事件

obj1.addEventListener('click',function(e){
            var e=e||window.event;
            if(e.target.nodeName.toLowerCase()=='ul'){
                alert(e.target.innerHTML);
            }

        },false);

两种方式来阻止事件冒泡。

方式一:event.stopPropagation();

$("#div1").mousedown(function(event){
event.stopPropagation();
});


方式二:return false;

$("#div1").mousedown(function(event){
return false;
});


但是这两种方式是有区别的。return false 不仅阻止了事件往上冒泡,而且阻止了事件本身。event.stopPropagation() 则只阻止事件往上冒泡,,如果点击一个链接,这个链接仍然会被打开.

event.preventDefault()

这是阻止默认事件的方法,调用此方法是,链接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;

 return false会同时阻止事件冒泡及默认事件;链接不会被打开,事件也不会传递到上一层的父元素;return false就等于同时调用了event.stopPropagation()和event.preventDefault()

 

为什么要用事件委托:

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,若是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?

在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;

每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤,哈哈),比如上面的100个li,就要占用100个内存空间,如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。

移除事件监听:element.removeEventListener(eventfunction,布尔值);

  • event.target 返回触发事件的元素(在点击事件中,就相当于被你点击的那个元素对象)
  • event.currentTarget 返回绑定事件的元素,即事件的委托对象(绑定了事件处理函数的元素)
    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="utf-8">
        <title>JS Bin</title>
    </head>
    
    <body>
        <ul>
            <li>hello 1</li>
            <li>hello 2</li>
            <li>hello 3</li>
            <li>hello 4</li>
        </ul>
        <script>
            let ul = document.querySelectorAll('ul')[0]
            let aLi = document.querySelectorAll('li')
            ul.addEventListener('click', function(e) {
                let oLi1 = e.target
                let oLi2 = e.currentTarget
               console.log(oLi1)//被点击的li
                console.log(oLi1 == aLi[0]) //  若点击第一个li,会返回true
                console.log(oLi2) // ul
                console.log(oLi1 === oLi2) // false
            })
        </script>
    </body>

     

 

posted @ 2021-02-27 17:44  sunmarvell  阅读(91)  评论(0编辑  收藏  举报