阅读 160

DOM事件模型与事件委托

DOM事件模型

 <div id="grandpa">     <div id="father">       <div id="son">文字       </div>     </div>   </div> 复制代码

假如给上面3个 div 分别添加事件监听 fnYe/fnBa/fnEr ,那么当点击 文字 的时候会先调用哪个事件?是先调用fnYe?还是先调用fnEr?

此时则需要一种约定来规范事件执行的顺序。

IE5认为应该先调用 fnEr
网景则认为应该先调用 fnYe

2002年,W3C发布了标准。文档名为 DOM Level 2 Events Specification
规定了浏览器应该同时支持两种调用顺序

即:
首先按  爷爷 -> 爸爸 -> 儿子 顺序看有没有函数监听
然后按  儿子 -> 爸爸 -> 爷爷 顺序看有没有函数监听
有监听函数就调用,并提供事件信息,没有就跳过

术语:
从外向内找监听函数,叫事件捕获
从内向外找监听函数,叫事件冒泡

事件捕获、冒泡.jpg

事件绑定API

.addEventListener('click',fn,bool) 复制代码

  • 如果bool不传或者为false

就让fn走冒泡,即当浏览器在冒泡阶段发现有监听函数,就回调用fn,并提供事件信息

  • 如果bool为true

就让fn走捕获,即当浏览器在捕获阶段发现有监听函数,就回调用fn,并提供事件信息

 --HTML-- <div id="grandpa">grandpa     <div id="father">father       <div id="son">son</div>     </div>   </div> --Javascript--    let fnYe = document.getElementById('grandpa') let fnBa = document.getElementById('father') let fnEr = document.getElementById('son') fnYe.addEventListener('click', function fn() {   console.log('爷爷') } ) fnBa.addEventListener('click', function fn() {   console.log('爸爸') } ) fnEr.addEventListener('click', function fn() {   console.log('儿子') })   复制代码

上面代码没有bool值,打印顺序为  儿子 爸爸 爷爷

 --HTML-- <div id="grandpa">grandpa     <div id="father">father       <div id="son">son</div>     </div>   </div> --Javascript--    let fnYe = document.getElementById('grandpa') let fnBa = document.getElementById('father') let fnEr = document.getElementById('son') fnYe.addEventListener('click', function fn() {   console.log('爷爷') },true) fnBa.addEventListener('click', function fn() {   console.log('爸爸') },true) fnEr.addEventListener('click', function fn() {   console.log('儿子') },true)   复制代码

上面代码bool值为true,打印顺序为  爷爷 爸爸 儿子

事件委托

由于事件会在冒泡阶段向上传播到父级元素,因此可以把子元素的监听函数绑定在父级元素上,由父级元素的监听函数统一处理多个子元素的事件。这种方法叫做事件委托。

例如,我们想要租房子。如果是我们自己租就比较麻烦,需要跑小区。此时我们可以委托中介帮我们操作,所谓的委托就是委托中介帮我们操作本应该由我们自己操作的事情。

  • 情景一

给100个按钮添加点击事件

倘若给每一个按钮都绑定点击事件,那将会占用大量内存。我们可以监听这100个按钮的祖先,等冒泡的时候判断target是不是这100个中的一个。

 --html-- <div id="div1">     <span>span</span>     <button data-id = "1号">click1</button>     <button>click2</button>     <button>click3</button>     <button>click4</button>     <button data-id = "5号">click5</button>     <button>click6</button>     ...     <button>click100</button>   </div>    --javascript--    div1.addEventListener('click', (e) => {   const t = e.target   if (t.tagName.toLowerCase() === 'button') {     console.log('botton被点击')     console.log('botton' + t.textContent + '被点击')     console.log('botton' + t.dataset.id + '被点击')   } }) 复制代码

  • 情景二

监听目前不存在的元素的点击事件

由于目前元素不存在,无法直接监听这个元素。但我们可以使用事件委托实现,监听祖先元素,等点击的时候看是不是想要的元素。

 --html-- <div id="div1">    </div>    --javascript--    setTimeout(()=>{   const button = document.createElement('button')   button.textContent = 'click'   div1.appendChild(button) },1000) div1.addEventListener('click', (e) => {   const t = e.target   if (t.tagName.toLowerCase() === 'button') {     console.log('botton被点击')   } }) 复制代码

事件委托的优点

  • 省内存,提高性能。

  • 可以监听动态元素。


作者:jwoonghuang
链接:https://juejin.cn/post/7026738178568486948


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐