事件流所描述的就是从页面中接受事件的顺序,分为事件捕获和事件冒泡两种形式。
一、事件之事件冒泡和事件捕获
事件流最早要从IE和网景公司的浏览器大战说起,IE提出的是冒泡流,而网景提出的是捕获流,后来在W3C组织的统一之下,JS支持了冒泡流和捕获流,但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,现行的主流是事件冒泡。
二、事件流的三个阶段
下面的图非常详细的描述了事件流的三个阶段:
红色箭头代表捕获阶段, 蓝色代表目标阶段, 绿色代表冒泡阶段
三、事件冒泡
事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点,是一种自下往上的顺序。
举个栗子,就很容易明白了。
1 | <!DOCTYPE html> |
在代码所示的页面中,如果点击了button,那么这个点击事件会按如下的顺序传播(Chrome浏览器):
button –> body –> document –> window
也就是说,click事件首先在<button>元素上发生,然后逐级向上传播。这就是事件冒泡。
四、 事件捕获
与事件冒泡正好相反,当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件,是一种自上而下的顺序。
事件捕获,为父元素截获事件提供了机会。
比如说刚才的demo,如果是事件捕获的话,事件发生顺序会是这样的:
window –> document –> body –> button
1 | var button = document.getElementById('clickMe'); |
addEventListener最后一个参数,为true则代表使用事件捕获模式,false则表示使用事件冒泡模式。
五、阻止事件冒泡
事件冒泡过程,是可以被阻止的。防止事件冒泡而带来不必要的错误和困扰。阻止冒泡的方法就是:stopPropagation()
1 | button.addEventListener('click', function(event) { |
六、判断事件所处的阶段
event对象都有一个属性eventPhase,表示调用事件处理程序的阶段,属性的值可以为1,2,3。 获取Event对象的target属性,代表当前的元素对象
1 | <body> |
使用事件代理,给父节点绑定监听事件,可以提升性能,可以减少绑定给每个子节点, 停止事件冒泡,调用Event对象的stopPropagation()方法,降低事件的复杂性