有dom节点如下:
<div id="parent">
<div id="son">
this is the son
</div>
</div>
<script>
var parent = document.getElementById('parent');
var son = document.getElementById('son');
parent.addEventListener('click',function(){
console.log('parent');
})
son.addEventListener('click',function(){
console.log('son');
});
</script>
-----------------------------------
| element1 |
| ------------------------- |
| |element2 | |
| ------------------------- |
| |
-----------------------------------
如果你是最初Event Object Model的设计者,那么你会设计成谁应该先执行click事件?(思考10s)
NetScape 说:parent上的事件先执行。为什么呢?因为这叫event capturing (事件捕获)。从技术上来讲的确是这样子的,一个 click 发生时,鼠标会触发一个系统中断并且告诉中断控制器,中断控制器会经过优先级排序后,最终决定是否将这个中断发给CPU,CPU在接收到中断后会去鼠标所对应的IO端口取得一系列的值,这些值是一些关于此次点击事件的参数,比如哪个键啊,点击的位置啊之类的,然后将这个click事件派送给处于active的进程,最终click事件首先被浏览器捕获,然后根据dom树向目标节点传递。最终会触发目标节点的事件监听函数。
| |
---------------| |-----------------
| element1 | | |
| -----------| |----------- |
| |element2 \ / | |
| ------------------------- |
| Event CAPTURING |
-----------------------------------
MicroSoft 说:son上的事件先执行。为什么呢?因为这叫event bubbling(事件冒泡)。NetScape你说的是有道理,但是我不听啊。你打我啊。技术实现是你说的这样子没错,但是我们就想一个很简单的问题:难道不应该是点击谁就触发谁酱紫才更符合我们人类的使用习惯吗?
/ \
---------------| |-----------------
| element1 | | |
| -----------| |----------- |
| |element2 | | | |
| ------------------------- |
| Event BUBBLING |
-----------------------------------
想想这样子的日子多蛋疼,web developer给一些列的节点绑定了事件监听,但是特么的在NetScape浏览器上和IE浏览器上一堆函数的执行顺序不一样。
w3c来了。他说:“你们不要吵了,大家都坐下来喝喝茶聊聊,这样子闹下去没有好的结果啊,对你们自己家的浏览器发展也没什么好处啊,这样吧,都听我的,我来想个办法吧。”
然后w3c的事件对象模型就出来了,方案是:我先按照NetScape捕获的顺序到达目标节点,然后再按照MicroSoft冒泡的顺序返回到window。这样总可以了吧,两个人都没有违背嘛。但是有个问题啊,这样子绑定在同一个节点上的事件岂不是要背执行两次?w3c说了:“是啊,按照正常是会被执行两次啊,但是我们可以让jser在写事件监听的时候自己选择啊,传个参数不就得了嘛”。有人问,如果忘了呢?“那就给他个默认的参数嘛”;于是乎:
| | / \
-----------------| |--| |-----------------
| element1 | | | | |
| -------------| |--| |----------- |
| |element2 \ / | | | |
| -------------------------------- |
| W3C event model |
------------------------------------------
element.addEventListener(event.type,callback[,boolen])
//第三个可选的参数是一个布尔值。
//如果是true,则此事件会在capturing的过程中被执行;
//如果是false则此事件会在bubbling的过程中被执行;
//默认不传是false.
浏览器事件触发顺序终于在w3c的斡旋下统一了,天下jser高歌欢庆。