严格来说stopPropagation与preventDefault其实没什么关系,一个是停止传播事件,一个是阻止默认的行为。
由于IE8并不兼容这两个方法,所以,我们如果需要考虑兼容性的话,应该这样写:
if (event.stopPropagation){
event.stopPropagation();
}
else{
event.cancelBubble=true;
}
if (event.preventDefault){
event.preventDefault();
}
else{
event.returnValue=false;
}
下面举个例子说明它们的区别 , test.jsp:
<html>
<head>
<script type="text/javascript" src="./media/js/jquery-1.12.4.min.js"></script>
<style type="text/css">
div,label,a,button{
display: inline-block;
}
</style>
</head>
<body>
<div style="margin-bottom: 10px;">
<label for="chk_stopPropagation">stopPropagation</label>
<input type="checkbox" id="chk_stopPropagation"/>
<label for="chk_preventDefault" style="margin-left: 20px;">preventDefault</label>
<input type="checkbox" id="chk_preventDefault"/>
</div>
<br/>
<div id="div_parent" style="width: 500px;height: 300px;background-color: green;color: white;">
<label>label parent</label>
<div id="div_sub_parent" style="margin:50px; width: 400px;height: 200px;background-color: red;color: white;">
<a id="lbl" style="margin: 50px;padding: 20px;background-color: gray;" href="http://www.baidu.com" target="_blank">
label on 'sub parent'
</a>
<form target="_blank" action="http://abccc" >
<input type="submit" οnclick="button_click();" style="padding: 10px;" value="Click me" id="btn_submit"/>
</form>
</div>
</div>
<br/>
<div id="log" style="width: 500px;height:300px;overflow: scroll;">
</div>
<script type="text/javascript">
function button_click(){
addLog("button is clicked.");
}
function setEvent(event){
if ($("#chk_preventDefault").prop("checked")){
if (event.preventDefault){
event.preventDefault();
}
else{
event.returnValue=false;
}
}
if ($("#chk_stopPropagation").prop("checked")){
if (event.stopPropagation){
event.stopPropagation();
}
else{
event.cancelBubble=true;
}
}
}
function addLog(pvLog){
$("#log").html($("#log").html()+"<br/>"+pvLog);
}
$(function(){
$("#div_sub_parent").click(function(){
addLog("div_sub_parent is clicked.");
setEvent(event);
});
$("#div_parent").click(function(){
addLog("div_parent is clicked.");
setEvent(event);
});
$("#lbl").click(function(){
addLog("hyperlink is clicked.");
setEvent(event);
});
$("#div_sub_parent").bind("click",function(){
addLog("div_sub_parent event2 is fired .")
});
$("#btn_submit").click(function(){
addLog("jQuery event1 fired: button is clicked.");
setEvent(event);
});
$("#btn_submit").click(function(){
addLog("jQuery event2 fired: button is clicked.");
});
//$("#lbl").trigger("click");
});
</script>
</body>
</html>
测试1:stopPropagation 和preventDefault 都不选,点击” label on 'sub parent'“, 输出日志:
hyperlink is clicked.
div_sub_parent is clicked.
div_sub_parent event2 is fired .
div_parent is clicked.
你会发现只是点击了这个链接而已,但是它的容器、容器的父容器什么的所有事件都会被触发个遍,而且链接默认的事件也触发了,它打开了百度网页链接!
测试2:刷新这个test.jsp,只勾上stopPropagation,然后再点击”label on 'sub parent'", 输出日志干净多了,只有一句hyperlink is clicked,也就是说stopPropagation会阻止链接以外的容器事件触发,事件到此为止,但默认的<a>行为正常触发, 它也打开了百度网页。
测试3:刷新这个test.jsp,stopPropagation和preventDefault两个checkbox都勾上,再点击"label on 'sub parent'",输出日志只有一句hyperlink is clicked,也不打开网页了, 通过与测试2的对比,preventDefault方法阻止了<a>原本默认的打开链接的事件,让其失效。
测试4:刷新这个test.jsp,什么都不勾,直接点击submit button,输出日志:
button is clicked.
jQuery event1 fired: button is clicked.
jQuery event2 fired: button is clicked.
div_sub_parent is clicked.
div_sub_parent event2 is fired .
div_parent is clicked.
哇,button在html代码里绑定的onclick事件、jquery绑定的两个click事件,button的父容器、父父容器的click事件全部触发!!!而且还不忘触发submit该做的动作:递交form数据 !
测试5:经过上面几次测试,现在我们已经非常明白stopPropagation的作用了,它阻止了事件向它的父容器扩散,但自身的事件多重事件却阻止不了,现在我们将两个checkbox都勾上,再点击button看日志:
button is clicked.
jQuery event1 fired: button is clicked.
jQuery event2 fired: button is clicked.
这时候因为用了preventDefault方法,成功阻止了默认的递交行为,也因为用了stopPropagation方法,阻止了事件向父容器扩散,但button自身被绑定的事件一件不漏地被依次执行。
但是假如需要彻底拦截button的原来所有click事件该如何做呢?在script节的后面添加如下代码:
document.getElementById("btn_submit").οnclick=null;
$("#btn_submit").unbind("click").click(function(){
addLog("jQuery new event fired: button is clicked.");
setEvent(event);
});
第一句不能少,因为jQuery的unbind影响不了原生的onclick事件,它的unbind只会对通过jQuery设置的事件起作用。