最近我在作前端面试题总结系列,感兴趣的朋友能够添加关注,欢迎指正、交流。html
争取每一个知识点可以多总结一些,至少要作到在面试时,针对每一个知识点均可以侃起来,不至于哑火。前端
在上一篇文章【前端 · 面试 】JavaScript 之你不必定会的基础题(一)中,有同窗产生了这样一个疑惑:为何 click 事件的监听函数中,this.id
和 event.target.id
的输出值是不同的?git
今天咱们就来扒一扒这其中的原理。面试
有以下的 HTML 文档结构:编程
<div id="parent"> <div id="child" class="child"> 点我 </div> </div>
第一次执行以下 JavaScript 代码:segmentfault
document.getElementById("parent").addEventListener("click", function () { alert(`parent 事件触发,` + this.id); }); document.getElementById("child").addEventListener("click", function () { alert(`child 事件触发,` + this.id); });
第二次执行另外一套 JavaScript 代码:浏览器
document.getElementById("parent").addEventListener("click", function (e) { alert(`parent 事件触发,` + e.target.id); }); document.getElementById("child").addEventListener("click", function (e) { alert(`child 事件触发,` + e.target.id); });
问题以下:函数
点击 id 为 child 的 div 后,JavaScript 代码的执行结果分别是什么?
答案是:post
对于这个答案中的第二次输出结果,有人生出了疑惑:为何 parent 事件触发时,e.target.id
的结果为 child呢?不该该是 parent 吗?学习
首先,咱们知道,HTML 页面上 DOM 元素的事件执行顺序通常有三个阶段:
整个过程以下图:
事件捕获和事件冒泡
当一个事件发生在具备父元素的元素上(例如,在咱们的例子中是 child 元素)时,现代浏览器运行两个不一样的阶段 - 捕获阶段和冒泡阶段。 在捕获阶段:
<html>
,是否在捕获阶段中注册了一个onclick
事件处理程序,若是是,则运行它。<html>
中单击元素的下一个祖先元素,并执行相同的操做,而后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。在冒泡阶段,偏偏相反:
onclick
事件处理程序,若是是,则运行它<html>
元素。这两个阶段以下图所示:
在现代浏览器中,默认状况下,全部事件处理程序都在
冒泡阶段进行注册,这也是为何只有一个阻止冒泡方法的方法
event.stopPropagation()
,而没有阻止捕获的方法,由于彻底不必。
首先,咱们得有一个清晰的认知:事件冒泡或者事件捕获,都是针对注册了事件的元素。
关于 this 和 event.target ,总结以下:
event.target
永远都指向真正触发了事件流程的元素 ,即处于事件触阶段的元素。event 还有一个属性 event.srcElement,它是 event.target 的别名,可是是一个非标准属性,尽可能不在生产环境中使用。
假若有如下代码:
parent.onclick = function1; child.onclick = function2;
当咱们点击 child 时,因为事件默认会在冒泡阶段注册,因此,不只会执行 function2,以后还会执行 function1,这样的结果可能不是咱们所指望的,咱们更但愿它们的点击事件之间互不影响。
若是要实现这点,只须要在 function2 中添加 event.stopPropagation()
便可。
如今咱们将题目中的 JavaScript 代码再增长一份:
document.getElementById("parent").addEventListener("click", function (e) { alert(`parent 事件触发,` + e.target.id); }, false); document.getElementById("child").addEventListener("click", function (e) { alert(`child 事件触发,` + e.target.id); }, true);
问题1:若是点击 child 元素,输出是什么?
问题2:若是点击 parent 元素,输出是什么?
能够看到,如今 parent 的点击事件是冒泡阶段执行,child 的点击事件是在 捕获阶段执行。
针对问题1,因为 parent 注册的是冒泡阶段执行,因此它的事件是在 child 触发阶段后的冒泡阶段执行的,因此答案应该是:先弹出 “child 事件触发,child”,再弹出“parent 事件触发,child”。
针对问题二,虽然 child 注册的是捕获阶段执行事件,可是 parent 事件流程的捕获根本走不到它,因此答案应该是:只弹出“parent 事件触发,parent”。
上面咱们分析了这么多,其实总结起来就下面几条:
小问题也有大根源,敢于发现,敢于探究!
~
~本文完,感谢阅读!
~
学习有趣的知识,结识有趣的朋友,塑造有趣的灵魂!
你们好,我是〖编程三昧〗的做者 隐逸王,个人公众号是『编程三昧』,欢迎关注,但愿你们多多指教!
你来,怀揣指望,我有墨香相迎! 你归,不管得失,惟以余韵相赠!
知识与技能并重,内力和外功兼修,理论和实践两手都要抓、两手都要硬!