资讯专栏INFORMATION COLUMN

简单聊聊浏览器JS事件触发机制

enrecul101 / 374人阅读

摘要:事件冒泡由微软提出,事件会从最内从的元素开始发生,再向外传播,正好与事件捕获相反。为了解决上述问题,我们可以利用事件委托的思想,在父级注册一个事件监听器,统一进行子元素的事件处理。

原理

事件捕获

由网景最先提出,事件会从最外层开始发生,直到最具体的元素,也就是说假如父元素与子元素都绑定有点击事件,又互相重叠,那么先出发的会是父元素的事件,然后再传递到子元素。

事件冒泡

由微软提出,事件会从最内从的元素开始发生,再向外传播,正好与事件捕获相反。

这两个概念都是为了解决页面中事件流的发生顺序,w3c采取了折中的办法,制定了统一的标准:先捕获再冒泡。

addEventListener

addEventListen(event, function, useCapture)添加事件的第三个参数默认值为false,即默认使用事件冒泡,若为true则使用事件捕获的机制,以下为示例:

当我们使用默认事件注册机制的时候,点击child元素时,会先后输出child,container,这就是事件冒泡机制:

container.addEventListener("click", () => console.log("container"))
child.addEventListener("click", () => console.log("child"))

将第三个参数设为true,点击child元素时,输出顺序就会变为container、child:

container.addEventListener("click", () => console.log("container"), true)
child.addEventListener("click", () => console.log("child"), true)

假若你希望点击child只打印child,不触发container的事件,我们就需要用到stopPropagation,它阻止捕获和冒泡阶段中当前事件的进一步传播:

container.addEventListener("click", () => console.log("container"))
child.addEventListener("click", (e) => {
  e.stopPropagation(); 
  console.log("child");
})

若你想要点击child只打印container,就需要进行捕获事件,并在container事件触发时进行阻止捕获:

container.addEventListener("click", (e) => {
  e.stopPropagation(); 
  console.log("container")
}, true)
child.addEventListener("click", () => console.log("child"), true)

与stopPropagation,还有一种事件方式叫做preventDefault,它的作用不是用于阻止冒泡,而是阻止浏览器默认行为,如a标签跳转,表单提交等。

事件委托

事件委托,又称为事件代理,通俗来讲是将元素的事件函数处理交由其他对象处理。它允许您避免向特定节点添加事件侦听器,我们这里所谈论的事件委托,与冒泡捕获流程相关,因此事件委托在此场景指的是子对象的处理事件交由父对象处理。

当你需要为一个动态的列表元素添加click事件时,若直接对列表项绑定事件,可能会重复注册很多个事件监听器。为了解决上述问题,我们可以利用事件委托的思想,在父级注册一个事件监听器,统一进行子元素的事件处理。

为了更好的说明,在这里举一个示例:

  • 1
  • 2
  • 3
  • 4
  • 5

为了给每一个li绑定上事件,若采用通常的方法,可能我们需要这样写代码:

document.querySelectorAll(".item").forEach(item => {
  item.onclick = e => handleClick(e.target.dataset.id)
})

但是列表数据可能会动态的变化,这样我们就避免不了动态的去注册事件,数量还可能很多,那有没有什么一劳永逸的方法呢?当然,让我们使用事件委托的方法,也就是将点击事件绑定到ul元素上:

document.querySelector(".list").onclick = e => {
  if (e.target.matches("li.item")) {
    handleClick(e.target.dataset.id)
  }
}

值得注意的是,event.target代表事件起源目标的引用,若要寻找当前注册事件对象的引用,请用event.currentTarget

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102291.html

相关文章

  • 聊聊Ajax那些事

    摘要:年初,许多事件使得被大众所接受。这使得应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减少用户等待时间,带来非常好的用户体验。调用方法后立即触发,若未被调用则不会触发此事件。 了解Ajax的起源、概念及特点 起源 该技术在1998年前后得到了应用。允许客户端脚本发送HTTP请求(XMLHTTP)的第一个组件由Outlook Web Access小组写成。该组...

    v1 评论0 收藏0
  • 聊聊Ajax那些事

    摘要:年初,许多事件使得被大众所接受。这使得应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减少用户等待时间,带来非常好的用户体验。调用方法后立即触发,若未被调用则不会触发此事件。 了解Ajax的起源、概念及特点 起源 该技术在1998年前后得到了应用。允许客户端脚本发送HTTP请求(XMLHTTP)的第一个组件由Outlook Web Access小组写成。该组...

    xzavier 评论0 收藏0
  • 聊聊Ajax那些事

    摘要:年初,许多事件使得被大众所接受。这使得应用程序更为迅捷地响应用户交互,并避免了在网络上发送那些没有改变的信息,减少用户等待时间,带来非常好的用户体验。调用方法后立即触发,若未被调用则不会触发此事件。 了解Ajax的起源、概念及特点 起源 该技术在1998年前后得到了应用。允许客户端脚本发送HTTP请求(XMLHTTP)的第一个组件由Outlook Web Access小组写成。该组...

    BigTomato 评论0 收藏0
  • 从一次报错聊聊 Point 事件

    摘要:定位问题根据调用栈很快定位到了代码,源码定位到之前一位同事写的组件代码,大概是这样的部分业务代码报错的地方部分业务代码发现是触发了事件,因为没有这个字段,导致抛出异常。它的和鼠标事件很像,非常容易迁移。 同步自我的博客,欢迎交流 这篇文章在草稿箱里躺了很久,因为最近又遇到了相关问题,于是又整理了一下。请注意这里讲的不是 css 的 pointer-events。 起因 从某个月黑风高的...

    quietin 评论0 收藏0
  • 聊聊Vue.js组件间通信的几种姿势

    摘要:子组件向父组件通信方法一使用事件父组件向子组件传递事件方法,子组件通过触发事件,回调给父组件。非父子组件兄弟组件之间的数据传递非父子组件通信,官方推荐使用一个实例作为中央事件总线。 写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出。 文章的原地址:https://github.com/answ...

    Profeel 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<