JavaScript中动态生成的元素需要绑定事件,经常会委托document来实现,但是如果document上绑定了其他的事件,比如对于一个元素点击其之外的区域使其隐藏,这个要给document绑定点击事件,就会导致委托的事件和document自身的点击事件发生重叠。
因此对document进行事件委托需要考虑其自身是否绑定了事件,或者将事件委托给动态生成组件的父级静态元素。
以一个demo为例:
实现效果:
前提:content是默认显示状态,info当做通过某个事件在其父级title内动态生成的标签
1.点击info,content由显示变为隐藏,或者反之
2.点击content之外,隐藏content
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
</head>
<style type="text/css" media="screen">
.title {
font-weight: bold;
margin-bottom: 30px;
cursor: pointer;
background: pink;
width: 150px
}
.content {
width: 150px;
height: 100px;
background: orange;
}
</style>
<body>
<div class="title">
<div class="info">点击显示或隐藏</div>
</div>
<div class="content">
<a href="http://baidu.com">链接1</a>
<a href="http://baidu.com">链接2</a>
<a href="http://baidu.com">链接3</a>
</div>
<script type="text/javascript">
$(document).ready(function(){
//定义阻止冒泡的函数
function stopFunc(e) {
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
}
//给document绑定点击事件,点击隐藏content
document.onclick = function (e) {
$(".content").hide();
}
//将info当做动态生成的组件,使用事件委托将其绑定点击事件
//注意:
//1.on之前先off,解除绑定在info上面的其他事件,方式点击过快导致事件累积
//2.这里将事件委托在了其非动态生成的父级.title上面,如果委托在document上面会导致与上面的document事件重叠
$('.title').off('click','.info').on("click",'.info',function (e) {
if ($(".content").css("display") == "none") {
$(".content").show();
} else {
$(".content").hide();
}
e = e || event;
stopFunc(e);
});
//点击content阻止冒泡,防止content隐藏
$('.content').bind("click", function (e) {
e = e || event;
stopFunc(e);
});
});
</script>
</body>
</html>
效果:
以上代码若将info的事件委托在document上面后,当第一次点击info,content就会隐藏,之后再点击info,content不会显示。