JS事件捕获与冒泡

先解释下事件捕获和冒泡:
捕获—事件从最上一级标签开始往下查找,直到捕获到事件目标(target)
冒泡—事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

在嵌套很多层的情况下, 如下:

html
<div class="div1" onclick="outer();">
    <div class="div2" onclick="middle();">
        <div class="div3" onclick="inner();"></div>
    </div>
</div>
css
.div1{width:300px;height:300px;border:1px solid red;}
.div2{width:200px;height:200px;border:1px solid green;}
.div3{width:100px;height:100px;border:1px solid blue;}
js
function html(){alert("html");} //加在html的onclick方法
function body1(){alert("body");}//加在body的onclick方法
function outer(){alert("outer");}
function middle(){alert("middle");}
function inner(){alert("inner");}
window.addEventListener("click", function(){alert("window");}) //加在window的onclick方法

当点击最深层的div3后,弹框顺序:
inner->middle->outer->body->html->window
网上有人说到body之后直接跳到window,但测试之后发现还是要到html,而window作为顶层对象,自然压轴登场(冒泡顺序和浏览器有关).所以由此看出, 事件冒泡机制是从里向外. 自然, 阻止冒泡也是有办法的, 如下:
当把function inner写成如下时,

function inner(e){
    alert("inner");
    e=e?e:event; //兼容低版本火狐
    // 阻止冒泡
    if(e.stopPropagation){ //webkit内核
        e.stopPropagation();
    }else{
        e.cancelBubble=true; //兼容IE9(含)以下
    }
}

再点击div inner, 弹框顺序是: inner;
是的, 只有一个弹框, 因为onclick事件默认是冒泡的顺序, 所以阻止冒泡后, 附加在目标(target)父级的点击方法全都不执行.
再进行测试, 如果采用捕获机制(这只在DOM3级事件才有—addEventListener), 所以我们对window绑定的点击事件进行改进, 不过在此之前, 我们先对addEventListener有更进一步的了解:

target.addEventListener(eventType, callback, isnotBubble);
/***
 *
 * eventType:  事件类型 string 必填
 * callback: 事件执行后的回调 function 必填
 * isnotBubble: 不冒泡 boolean 非必填
 * value of isnotBubble: false(默认值)---冒泡(从里向外);true---捕获(从外向里)
 *
***/

现在对window进行改进, 如下:

window.addEventListener("click", function(){alert("window");}, true); //事件捕获阶段

执行div inner的点击事件, 弹框顺序为: window->inner;
再执行div outer的点击事件, 弹框顺序为: window->outer->body->html.
大多数情况下, 很少会用到事件捕获阶段…

如果把div标签换成button, 会发生什么情况呢, 如下:

html
<button class="btn1" onclick="btnOuter();">
    <button class="bnt2" onclick="btnMiddle();">
        <a class="btn3" href="javascript:void(0);" onclick="btnInner();">链接</a>
    </button>
</button>
css
.btn1, .btn2, .btn3{display:block;}
.btn1{width:100px;border:1px solid red;}
.btn1{width:70px;border:1px solid green;}
.btn1{width:40px;border:1px solid blue;}
js
function btnOuter(){alert("btnOuter");}
function btnMiddle(){alert("btnMiddle");}
function btnInner(){alert("btnInner");}

而布局完全不是预想中的样子:

// 浏览器渲染后的布局
<button class="btn1" onclick="btnOuter();"></button>
<button class="bnt2" onclick="btnMiddle();">
        <a class="btn3" href="javascript:void(0);" onclick="btnInner();">链接</a>
</button>

如果有人不信的话, 可以自己去试试
而对于a.href=urlbutton.type=submitinput.type=submit 等类似的标签, 都会在点击后执行自己标签的默认事件, 比如a标签会跳页面, button会提交表单, 但是在某些时候我们并不希望标签执行自己的默认事件, 所以再进行改进:
function btnInside改进如下

html
<button class="btn1" onclick="btnOuter();">
    <button class="bnt2" onclick="btnMiddle();">
        <a class="btn3" href="http://www.baidu.com" onclick="btnInner(event);">链接</a>
    </button>
</button>
js
function btnInner(e){
        e.preventDefault() || (window.event.returnValue=false); //兼容IE
        alert("btnInner");
    }

此时点击a btn3, 不会跳页面.

最后再加一句: IE9(不含)以下竟然不支持addEventListener方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值