现在我们有这样一个需求:有一个按钮,我们点击它的时候屏幕上会出现一个div,而当我们点击屏幕任意空白处的时候,div消失。
点击空白处消失,这个需求应用还是比较广泛的,但是实施起来却不是那么顺利。
html:
<button>出现</button>
<div></div>
css:
div{
display: none;
width:100px;
height:100px;
background: pink;
}
1、我们来为按钮添加一个点击事件,可以顺利执行,点击后div出现。
var btn=document.getElementsByTagName("button")[0];
var div=document.getElementsByTagName("div")[0];
btn.onclick = function () {
div.style.display="block";
}
2、我们为document添加点击事件,使div消失。
document.onclick = function () {
div.style.display="none";
}
这个时候我们发现我们的btn的点击事件居然失效了,怎么点都出不来。
这涉及到一个问题——事件冒泡
在JS中,当一个元素接收到事件,会把接收到的事件一次传给它的父元素,直到window。
刚刚我们点击按钮,却传到了它的父元素,如body,所以默认就执行了我们document的点击事件,导致div一直是消失状态。我们要做的就是阻止事件冒泡。
3、解决方案:阻止事件冒泡
在事件函数内获取事件,并添加stopPropagation方法:
btn.onclick = function (ev) {
div.style.display="block";
var ev = window.event||ev; //ev传入参数并且放在这里是为了兼容低版本火狐浏览器,其它使用window.event即可,为兼容全部写入。
ev.stopPropagation();
}
我们的代码可以正常运行了,但是stopPropagation方法在低版本ie是不兼容的(本人测试ie8不兼容),为兼容,我们使用ie专有的cancelBubble=true的方法。
兼容ie8:
btn.onclick = function (ev) {
div.style.display="block";
var ev = window.event||ev; //ev传入参数并且放在这里是为了兼容低版本火狐浏览器,其它使用window.event即可,为兼容全部写入。
ev.cancelBubble=true;
}
全部兼容,可使用一个三目运算符判断使用:
btn.onclick = function (ev) {
div.style.display="block";
var ev = window.event||ev;
ev.stopPropagation? ev.stopPropagation():ev.cancelBubble=true;
}
这样就可以完美运行啦,按钮事件不会再传递到父元素了。