js事件委托

更新日期: 2020-02-21阅读: 2.3k标签: 事件

今天呢,咱们来说说事件委托,有的相关资料叫事件代理.首先呢,先来讲讲事件委托的起源:由于事件处理程序可以为web应用提供交互能力,因此很多开发人员会不分青红皂白的向页面中添加大量的处理程序.在js中,添加到页面的事件处理程序数量直接关系到页面的整体运维性能.导致这一问题的原因是多方面的.首先:

1 函数都是对象,都会占用内存,内存中对象越多,性能越差
2 事先指定所有的事件处理程序而导致dom访问次数,会延迟整个页面的交互的就绪事件.

所以:对事件处理程序过多问题的解决方案就是事件委托.


举个栗子

 <ul id = 'ul1'>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    ...
    <li>100</li>
 </ul>

 如果咱们页面上有100个li标签,如果要实现点击li变成红色,我们虽然可以用for循环,给每个li添加事件,那这样就为它们添加了100个事件处理程序,若在一个复杂的web程序中,都使用这种方式,那结果就是数不清的添加事件处理.那么这里是极其浪费资源的.所以这里可以得到一个结论:

事件委托,最重要的功能就是提高程序运行效率.

既然出来了事件委托,那咱们讲讲事件委托的原理.先来个概念:事件流.

​事件流分为
​ 1.事件捕获
当一个事件触发后,从Window对象触发,不断经过下级节点,直到目标节点。在事件到达目标节点之前的过程就是捕获阶段。所有经过的节点,都会触发对应的事件
​ 2.事件冒泡
 当事件到达目标节点后,会沿着捕获阶段的路线原路返回。同样,所有经过的节点,都会触发对应的事件

那现在直接上代码,带大家来了解什么是事件捕获和事件冒泡

  <div id = 'div1'>
       爷爷
        <div id = 'div2'>
           父亲
          <div id = 'div3'>
            孙子
          </div>
        </div>
   </div>
 <style>
     div{padding: 50px; color: white; font-size: 20px;}
     #div1{background-color: orange;}
     #div2{background-color: blue;}
     #div3{background-color: red;}
 <style>

例如,咱们都给这三个div同时绑定了点击事件,那我在点击孙子时,按常理来说,是不是也是点击了父亲和爷爷呢,所以呢,咱们点击了孙子的click事件,那么这个事件就会向dom树上传播,也就是这个顺序

  div3>div2>div1>body>html>document.....

那么呢,这就是事件冒泡,而事件捕获正好相反,在事件捕获过程中,document首先接到click事件,然后沿着document向下,一直传播到事件的实际目标.也就是按着这个顺序

   document>html>body>div1>div2>div3

但传统的事件的绑定没有办法实现事件捕获的,咱们的默认事件流还是事件冒泡!
    事件冒泡:由里向外逐级向外触发(必须由父子关系的组件)(默认事件流)
    事件捕获:由外向里逐级向外触发(必须由父子关系的组件) 传统的事件的绑定没有办法实现
 好,这里有人问了,既然咱们讲的是事件委托,为什么这里要将事件流的事件冒泡和事件捕获呢.其实咱们要实现的事件委托原理就是事件冒泡!那接着来说咱们上述的案例,现在需求来了,如果要给100个,1000个li标签同时绑定onclick事件,咱们这里用最高效的方式进行绑定,没错,就是事件委托.
html <ul id = 'ul1'> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> ... <li>100</li> </ul>
要给这100个li标签绑定事件,当我们单击li时,当前被点击的li标签背景显示红色.同时呢,这里又产生了一个问题:父级那么多子元素,怎么区分事件本应该是哪个子元素的?答案是咱们的事件中有个event对象,而event对象里记录的有“事件源”,它就是发生事件的子元素。咱们在写的时候,这个获取event的事件源是有IE兼容性的. 在低版本中的获取是window.event.srcElement;而在咱们其他浏览器是可以直接通过event.target获取的,咱们一般的写法是

  var target = event.target || window.event.srcElement;//短路操作

那咱们通过事件委托来实现

      var oUl = document.getElementById("ul1");
      //委托ul上的点击事件,将当前点击的li节点变成红色。
      oUl.onclick = function(ev){
           //获取事件对象短路操作,兼容IE
           var e = ev || window.event;
           //获取事件源 target  这里也要兼容IE
           var target = e.target || window.event.srcElement;
           //判断target是否符合要求的元素节点
           if(target.tagName.toLowerCase() == "li"){
             //将当前点击这个li节点变成红色
             target.style.backgroundColor = 'red';
            }
      }

这里咱们就真真实实的实现了一个事件委托,而且,就只绑定了一个事件,把这个事件给了ul标签.咱们通过点击li,然后通过冒泡原理 子元素身上的事件会冒泡到父元素身上 那这里是不是比传统的实现方式方便了很多呢,而且节省了大量的内存资源.没有那么多事件处理程序了,这是对web程序的一个性能的优化.综上,可以总结出要实现事件委托,必须遵从的三个条件:
     1、找要添加行为的节点的父节点或者祖先节点
     2、将事件绑定在找到的父节点上
     3、找到触发对象,判断是否符合要求,如果符合要求,进行后续操作。
其实事件委托的好处不仅止于此,再来个需求,在页面上给一个按钮,通过点击按钮,然后给ul标签新加一个ul标签.那这个新加的li标签,也要实现上面兄弟级一样的功能.传统事件中,咱们需要为新加的绑定事件,那不是非常的麻烦吗.

  //为了给新加标签内容标识
   var i = 6;
   var oBtn = document.getElementById("btn1");
   oBtn.onclick = function(){
     //创建一个新的li标签
     var newLi = document.createElement("li");
     //给新加的标签添加内容
     newLi.innerHTML = 111 * i++;
     //将新加的li标签,添加到ul元素的末尾
      oUl.appendChild(newLi);
  }

我们这里通过事件委托来实现,上述新加的li标签,同样也享受li兄弟级的一样的功能.那就是后添加节点,拥有前面绑定好的函数。


事件委托的优点:
      1.提高性能:每一个函数都会占用内存空间,只需添加一个事件处理程序代理所有事件,所占用的内存空间更少。
      2.动态监听:使用事件委托可以自动绑定动态添加的元素,即新增的节点不需要主动添加也可以一样具有和其他元素一样的事件。

原文:https://www.cnblogs.com/lechar/archive/2020/02/28/12375421.html

链接: https://www.fly63.com/article/detial/7964

js中addEventListener事件监听器参数详解

我们都知道addEventListener() 的参数约定是:useCapture是可选参数,默认值为false,目前DOM 规范做了修订:addEventListener() 的第三个参数可以是个对象值了。passive就是告诉浏览器我可不可以用stopPropagation...

js监听浏览器返回,pushState,popstate 事件,window.history对象

在WebApp或浏览器中,会有点击返回、后退、上一页等按钮实现自己的关闭页面、调整到指定页面、确认离开页面或执行一些其它操作的需求。可以使用 popstate 事件进行监听返回、后退、上一页操作。

CSS中的pointer-events属性实现点穿效果

具有层级关系的结构中,使用了pointer-events:none 属性将会使当前元素中的事件不会被捕获,从而实现了点穿的效果。而当代码示例中假如top元素具有子元素且显示指定pointer-events属性不为none的时候,top元素注册的事件将会被捕获/冒泡触发

js鼠标事件参数,获取鼠标在网页中的坐标

事件对象 event,JavaScript 将事件event作为参数传递,IE中把 event 事件对象作为全局对象 window 的一个属性,获取鼠标在网页中的坐标 = 鼠标在视窗中的坐标 + 浏览器滚动条坐标

js事件冒泡和默认事件处理(原生js、vue)

何为默认事件?比如 a 会跳转页面,submit 会提交表单等。普通js方法:e.preventDefault()函数。Vue.js方法: .prevent 是vue 的内置修饰符,调用了 event.preventDefault()阻止默认事件

js keyup、keypress和keydown事件 详解

js keyup、keypress和keydown事件都是有关于键盘的事件,当一个按键被pressed 或released在每一个现代浏览器中,都可能有三种客户端事件。

深入nodejs-核心模块Events详解(事件驱动)

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 使用了一个事件驱动、非阻塞式 I/O的模型,使其轻量又高效。比如,文件操作中的fs事件流,网络编程所用到的tcp,http模块等,当你回想自己写的程序后,会发现很多操作都基于事件驱动,Events类。

纯CSS实现点击事件展现隐藏div菜单列表/元素切换

在写移动端导航的时候经常用到点击按钮出现/隐藏导航条的情况,最常见的方法当然还是前端框架直接调用,省心省力,不易出错;当然还有使用纯JS实现的小代码段。我这里整理了纯CSS实现方式,给需要的人和给自己做个笔记:实现原理利用CSS伪类:target

关于鼠标移动太快导致moseleave事件不触发的问题

我做的是一个table的编辑功能,当移入某行的时候展示编辑状态,在移出某行的时候显示的是原始状态,此时遇到一种情况,就是.当mousenter事件触发之后,由于鼠标移动得太快,同一个tr上绑定的mouseleave事件压根儿就没有执行。

Js事件传播流程

js事件传播流程主要分三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。在我们平常用的addEventListener方法中,一般只会用到两个参数,一个是需要绑定的事件,另一个是触发事件后要执行的函数

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!