资讯专栏INFORMATION COLUMN

JS专题之事件模型

W4n9Hu1 / 799人阅读

摘要:三事件流规定事件包括三个阶段,事件捕获,处于目标阶段事件冒泡。一起来看添加新增加的,点击发现没有反应,说明事件没有绑定进去,但是我们也并不想,每增加一个新元素,就为这个新元素绑定事件,重复低效率的工作应当避免去做。

本文共 1960 字,读完只需 8 分钟
事件

用户与网页交互是通过事件实现的,事件刚开始是作为分担服务器负载的一个手段,起初没有统一的规范,直到 DOM2 级,网景和 IE 才开始有各自的 API 规范。

对于事件的触发机制,两个公司都认为页面的触发机制并不只是点击了某个元素,就只触发当前目标元素的事件。

比方说:页面有多个同心圆,当点击最里面的圆时,你其实也点击了包含这个圆外面的那些圆。 两个公司对这点的认同是一致的,但是事件流的传播顺序上采用了不同的两种方案来实现,即事件冒泡和事件捕获。

一、事件冒泡

IE 浏览器从老版本开始就一直支持事件冒泡机制,所谓事件冒泡,指事件流开始是从较为具体的元素接收,一直传播上不具体的元素上。

就是从目标元素传播到父级元素。


    

如下图所示,如果点击了 id 为 child 的元素后,事件流会从 child 一直传播到 window 对象。

所有现代浏览器都支持事件冒泡。

二、事件捕获

由网景公司主导的事件捕获则刚好和事件冒泡相反,事件流开始从不具体的元素触发,然后传播到具体的元素上。简而言之就是从父级元素传播到目标元素。

由于事件捕获是从 IE 9开始支持,不兼容老版本浏览器,所以使用的人比较少。

三、事件流

DOM 规定事件包括三个阶段,事件捕获,处于目标阶段、事件冒泡。

从 IE 9 开始的浏览器规定,事件流的顺序先是事件捕获,会截获到事件,然后是处于目标阶段,实际的目标接收到事件,最后是事件冒泡,可以在这个阶段对事件进行响应。

以之前的 child 元素为例,直到 child 元素接收到事件前(从 window 到 parent),都是事件捕获阶段。到了 child 元素,此时对事件进行处理,随后冒泡到 window 对象上,冒泡阶段也是可以对事件进行处理的。 基于事件冒泡能对事件进行处理的特点,随后将讲到与其有关的事件委托机制。

四、事件绑定

HTML 与 事件的绑定有三种形式:

1. 
2. var childEl = document.getElementById("child"); childEl.onclick = function() { console.log("hello"); } 3. var childEl = document.getElementById("child"); childEl.addEventListener("click", function() { console.log("hello"); }, false);

JavaScript 是单线程的语言,在遇到元素有事件触发时,会在事件队列中寻找有没有与这个事件绑定的函数,如果没有则什么都不做,如果有,则将该函数放到事件队列的前面,等待主线程事件执行完毕后执行。

上述代码第一种绑定,将事件写在 html 中,表现和行为没有解耦,是不建议这样写代码的。

第二种绑定,将事件绑定在元素对象上,这种写法主要是容易发生事件的覆盖。

第三种绑定,首先,第三个参数为布尔值,默认为 false, 表示在事件冒泡阶段调用事件处理程序,如果为 true, 则表示在事件捕获阶段调用事件处理函数。

当我们想处理完一次事件后,将不想在处理该元素的事件绑定时,应该将元素的事件绑定置为空,如果容易发生内存泄漏。

第一种写法:
childEl.onclick = null;


第三种写法:
function eventHandler() {
    console.log("hello");
}

childEl.addEventListener("click", eventHandler, false);

childEl.removeEventListener("click", eventHandler, false);
五、事件委托(事件代理)

事件委托是利用事件冒泡的性质,事件流开始是从较为具体的元素接收,一直传播上不具体的元素上。

首先,假如有一个列表 ul,每个列表元素 li 点击会触发事件处理程序,显然,如果一个一个地给元素绑定事件, 效率肯定不好。

与此同时,当新增一个元素时,事件不见得会绑定成功。一起来看:




新增加的 menu-new,点击发现没有反应,说明事件没有绑定进去,但是我们也并不想,每增加一个新元素,就为这个新元素绑定事件,重复低效率的工作应当避免去做。

我们通过事件委托的思路来想,事件流的传播,目标元素本身依然会有事件,但同时,冒泡出去后,更高层次的 dom 也能处理事件程序。那么,我们只需要给高层次节点绑定事件,通过判断具体是触发的哪个子节点,再做相应的事件处理。




menu 列表的每个子菜单元素的事件都能正确响应,新增的 menu-new 同样也能正确响应事件。

事件委托的好处在于,我们不用给每个元素都一一地手动添加绑定事件,避免重复低效的工作。

其次,事件委托更少得获取 dom, 初始化元素对象和事件函数,能有效减少内存占用。

每当将事件程序指定给元素时,html 代码和 js 代码之间就建立了一个连接,这种连接越多,网页就执行起来越慢,所以事件委托能有效减少连接树,提高网页性能。

总结

用户与网页的交互是通过事件进行的,事件模型分为事件冒泡和事件捕获,事件冒泡的兼容性更好,应用更广,同时通过事件冒泡,可以建立事件委托,提升网页性能。

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

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

相关文章

  • [面试专题]JS事件模型

    摘要:在这个事件发生期间,调用可阻止滚动当手指从屏幕上移开时触发。关于此事件的确切触发事件,文档中没有明确说明。特定于事件目标的对象的数组。 JS事件模型 事件模型以及周边 事件捕获 事件冒泡 事件触发 移动端事件模拟 事件委托 事件流 事件捕获(event capturing)&事件冒泡(event bubbling) 给inner,out均绑定点击事件.点击inne...

    lindroid 评论0 收藏0
  • JS专题事件循环

    摘要:宏任务需要多次事件循环才能执行完。总结事件循环是和事件调用机制的核心,保证了页面可以有序无阻塞的进行。事件循环的主要逻辑是先执行调用栈,直到清空调用栈只剩下全局上下文。微任务执行后完,进行页面渲染和垃圾回收后进行下一轮事件循环。 准备知识 1. 进程(process) 进程是系统资源分配一个独立单位,一个程序至少有一个进程。比方说:一个工厂代表一个 CPU, 一个车间就是一个进程,任一...

    mengera88 评论0 收藏0
  • JS专题数组去重

    摘要:将元素作为对象的键,默认键对应的值为如果对象中没有这个键,则将这个元素放入结果数组中去。 前言 数组去重在日常开发中的使用频率还是较高的,也是网上随便一抓一大把的话题,所以,我写这篇文章目的在于归纳和总结,既然很多人都在提的数组去重,自己到底了解多少呢。又或者是如果自己在开发中遇到了去重的需求,自己能想到更好的解决方案吗。 这次我们来理一理怎么做数组去重才能做得最合适,既要考虑兼容性,...

    only_do 评论0 收藏0
  • JS异步编程callback

    摘要:而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果而是在调用发出后,被调用者通过状态通知来通知调用者,或通过回调函数处理这个调用。总结回调函数是异步编程中的基石,但同时也存在很多问题,不太适合人类自然语言的线性思维习惯。 为什么 JS 是单线程? 众所周知,Javascript 语言的执行环境是单线程(single thread)。 所谓单线程,就是指一次只能完成一...

    superw 评论0 收藏0
  • [面试专题]一线互联网大厂面试总结

    摘要:道阻且长啊前端面试总结前端面试笔试面试腾讯一面浏览器工作原理浏览器的主要组件包括用户界面包括地址栏后退前进按钮书签目录浏览器引擎用来查询及操作渲染引擎的接口渲染引擎渲染界面和是基于两种渲染引擎构建的,使用自主研发的渲染引擎,和都使用网络用来 道阻且长啊TAT(前端面试总结) 前端 面试 笔试 面试 腾讯一面 1.浏览器工作原理 浏览器的主要组件包括: 用户界面- 包括地址栏、后退/前...

    lemanli 评论0 收藏0

发表评论

0条评论

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