您的位置:首页 > Web前端 > JavaScript

js核心基础之Events事件机制(事件冒泡、事件捕获、事件执行顺序、阻止冒泡)

2018-01-16 19:51 836 查看
事件的触发有三个阶段:

1、document往事件触发地点,捕获前进,遇到相同注册事件立即触发执行;

2、到达事件位置,触发事件;

3、事件触发地点往document方向,冒泡前进,遇到相同注册事件立即触发。

注意:无论是冒泡阶段还是捕获阶段触发,都只会触发一次。默认为冒泡模式

例子:

简写的节点树:document->html->body->outdiv->innerdiv

先捕获再冒泡:遍历顺序;

//捕获阶段
document->html->body->outdiv->innerdiv
//冒泡阶段
innerdiv->outdiv->body->html->document


<div id="outdiv">
out div
<div id="innerdiv">
innerdiv
</div>
</div>
var outdiv = document.getElementById('outdiv');
var innerdiv = document.getElementById('innerdiv');


//捕获模式
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 捕获模式', event);
}, true)
outdiv.addEventListener('click', function (event) {
console.log('outdiv 捕获模式 ', event);
}, true)
// result: outdiv then innerdiv


原理:捕获模式,即在捕获阶段触发该函数,当在捕获阶段,即第一遍还未遍历完成,引擎遍历到outdiv上时发现该节点上注册了click函数,就立即触发outdiv上的click,

而后,遍历到innerdiv上,发现也注册了click事件,就触发innerdiv的click事件。

//冒泡模式
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 冒泡模式', event);
}, false)
outdiv.addEventListener('click', function (event) {
console.log('outdiv 冒泡模式 ', event);
}, false)
//result innerdiv then outdiv


原理:冒泡模式,即在冒泡阶段触发该函数,当在捕获阶段,即便遍历到outdiv时,发现,其身上注册了事件,也不会触发,只有等到冒泡阶段,而冒泡阶段是先遍历到innerdiv,

所以会先触发innerdiv上的click。

总结:当innerdiv 和outdiv分别使用不同模式的时候,则谁是捕获模式,就先触发当前节点上注册的事件。

二、注意点

1、在同一个节点上,事件注册的顺序,会影响它的执行顺序,。

//捕获和冒泡模式下都注册
outdiv.addEventListener('click', function (event) {
console.log('outdiv 捕获模式 ', event);
}, true)
outdiv.addEventListener('click', function (event) {
console.log('outdiv 冒泡模式 ', event);
}, false)
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 捕获模式', event);
}, true)
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 冒泡模式', event);
}, false)
// result outdiv innerdiv then innerdiv outdiv


outdiv.addEventListener('click', function (event) {
console.log('outdiv 捕获模式 ', event);
}, true);
outdiv.addEventListener('click', function (event) {
console.log('outdiv 冒泡模式 ', event);
}, false);
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 冒泡模式', event);
}, false);
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv 捕获模式', event);
}, true);
// result outdiv 捕获 innerdiv 冒泡 then innerdiv捕获 outdiv冒泡


总结: 非目标元素捕获 -> 目标元素代码顺序 -> 非目标元素冒泡。

2、event.stopPropagation()

并不是说,在冒泡阶段阻止事件的发生,而是不仅阻止了事件的冒泡,还阻止事件的继续捕获,简而言之,就是阻止事件的进一步传播。

所以,当事件都是在捕获阶段注册,也是能够阻止的;

例子:

outdiv.addEventListener('click', function (event) {
console.log('outdiv ', event);
}, false);
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv', event);
event.stopPropagation();
}, false);


原理:两个事件谁先触发,谁才能阻止后一个事件的触发

比如,当两个事件都是冒泡阶段,如果不做任何操作,所以innerdiv的click事件,先于outdiv触发,

所以,在innerdiv里面写上,stoppropagation,是能够阻止outdiv的click事件的触发的

outdiv.addEventListener('click', function (event) {
console.log('outdiv ', event);
event.stopPropagation();
}, true);
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv', event);
}, true);


再比如,当两个事件都是捕获阶段触发,如果不做任何操作,outdiv的click事件,先于innerdiv触发,

所以 ,只能 在outdiv里面写上stoppropagation,才能阻止innerdiv的click事件的触发,但是,问题来了,

既然这样,那么innerdiv上面的事件再也触发不了,其实,也不用担心,因为,我们日常所使用的事件都是在冒泡阶段触发的,

换句话说,点击子节点可以决定是否触发父节点的click,但是,点击父节点,不能决定是否触发子节点的click。

3、stopImmediatePropagation()

例子,

innerdiv.addEventListener('click', function (event) {
console.log('innerdiv', event);
event.stopImmediatePropagation();
}, false);
innerdiv.addEventListener('click', function (event) {
console.log('innerdiv22222', event);
}, false);
//result:    innerdiv
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐