什么是事件
事件是用户在操作浏览器窗口里的内容时,发生的交互瞬间。比如 onclick、onmouseenter、onmouseleave都是事件;
当我们点击一个内容,或者按下某个键;事件也可能是浏览器中发生的事情,比如某个页面加载完成,或者是窗口滚动、浏览器窗口大小被改变。
什么是事件机制
事件机制也叫做事件模型、事件流,意思就是从页面里接受事件的顺序;
主要分为两种:事件捕获和事件冒泡。
举例:
// html:
<div id="yeye">
<div id="baba">
<div id="erzi">
文字
</div>
</div>
</div>
// 即:爷爷>爸爸>儿子
给三个div分别添加事件监听:fnYe、fnBa、fnEr;
问题1
点击文字,算不算点击儿子?
点击文字,算不算点击爸爸?
点击文字,算不算点击爷爷?
答案:
都算,点文字,既算点击了儿子,也算点击了爸爸和爷爷元素。
问题2
三个元素都有事件监听,那么点击文字的时候,应该先调用哪个函数呢?
答案:
IE5团队认为:应该先调用fnEr,然后调用fnBa,最后是fnYe;
网景团队认为:应该先调用fnYe,然后调用fnBa,最后是fnEr;
最后W3C在2002年发布了标准:DOM Level2 Events Specification,规定了浏览器应该同时支持这两种调用顺序:
首先按 爷爷 → 爸爸 → 儿子 顺序看有没有函数监听;
然后按 儿子 → 爸爸 → 爷爷 顺序看有没有函数监听;
有监听函数就调用,并且提供相应的事件信息,没有就跳过。
捕获和冒泡
像 爷爷 → 爸爸 → 儿子 这种顺序来执行事件的顺序叫 事件捕获
像 儿子 → 爸爸 → 爷爷 这种顺序来执行事件的顺序叫 事件冒泡
即 从外向内 找监听函数,叫 事件捕获 ; 从内向外 找监听函数,叫 事件冒泡;
问题3
既然要先捕获,再冒泡,那岂不是fnYe、fnBa、fnEr每个函数都要调用两次?
答案:不是,因为开发者可以自己选择把函数放在捕获阶段还是冒泡阶段,定好放在哪个阶段,另外一个阶段就不会执行了;
如何选择把函数放在哪个阶段执行呢?
通过addEventListener这个API来决定:
baba.addEventListener('click',fnBa,bool)
这里的bool值如果不写,或者写一个falsy值,那么函数fn就会走冒泡的顺序。即浏览器在冒泡阶段发现baba元素有监听函数,就会调用并且提供事件信息。
这里的bool值如果写true,就会走捕获的顺序。即浏览器在捕获阶段发现baba元素有监听函数,就会调用并且提供事件信息。
所以我们可以通过修改addEventListener()里的bool值来决定函数走哪个事件顺序,在哪个阶段被调用;
示意图: