Event Delegation(事件委托):简而言之,依赖于事件冒泡机制,当我们对 DOM 中的某个元素添加事件的时候,我们可以将事件添加到它的父节点上,即将事件委托给父节点,由父节点来处理事件的响应。
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Event Delegation</title>
</head>
<body>
<div id="container">
<ul id="list">
<li><a href="#">Item #1</a></li>
<li><a href="#">Item #2</a></li>
<li><a href="#">Item #3</a></li>
<li><a href="#">Item #4</a></li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// 对列表中的<a>元素添加事件
$("#list a").on("click", function(event) {
console.log($(this).text());
});
});
</script>
</body>
</html>
如图所示,当我们单击列表中的每一项(<li>
元素)时,都会触发点击事件并在 console 中打印出相应信息。现在,我们新增一项(<li>
元素)到列表中,测试新增元素的事件是否能够正常触发:
$("#list").append( "<li><a href='#'>Item #5</a></li>" );
可以看到,新增元素的事件没有被正常触发,这是因为新增<li>
元素的代码晚于事件注册的代码执行。在某些情况下,我们可能会对列表中的<li>
元素进行频繁的新增、删除操作,那么以上示例代码中对<a>
元素的事件注册方式就显得不合理。现在,我们修改以上示例代码,如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Event Delegation</title>
</head>
<body>
<div id="container">
<ul id="list">
<li><a href="#">Item #1</a></li>
<li><a href="#">Item #2</a></li>
<li><a href="#">Item #3</a></li>
<li><a href="#">Item #4</a></li>
</ul>
</div>
<script src="js/jQuery/jquery-3.1.0.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// 创建委托事件,即我们将事件注册在父元素<ul>上,将事件目标设置为<a>元素
$("#list").on("click", "a", function(event) {
console.log($(this).text());
});
// 新增<li>元素
$("#list").append("<li><a href='#'>Item #5</a></li>");
});
</script>
</body>
</html>
经过测试,列表中的每一项(<li>
元素)的事件都被正常触发并显示相应信息。在单击列表中的每一项(<li>
元素)时,正真的事件源是<a>
元素,依赖于事件冒泡机制,单击事件会被上传到每一层父节点,事件传播顺序如下所示:
<a>
<li>
<ul #list>
<div #container>
<body>
<html>
document root
以上示例代码引入了 jQuery 代码库,现在贴出原汁原味版:
<!-- 缺陷代码 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Event Delegation</title>
</head>
<body>
<div id="container">
<ul id="list">
<li><a href="#">Item #1</a></li>
<li><a href="#">Item #2</a></li>
<li><a href="#">Item #3</a></li>
<li><a href="#">Item #4</a></li>
</ul>
</div>
<script type="text/javascript">
window.onload = function() {
var ul = document.getElementById("list");
var arr = ul.getElementsByTagName("a");
for (var i = 0, l = arr.length; i < l; i++) {
arr[i].onclick = function eventHandler() {
console.log(this.textContent);
};
}
}
</script>
</body>
</html>
<!-- 改进代码 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Event Delegation</title>
</head>
<body>
<div id="container">
<ul id="list">
<li><a href="#">Item #1</a></li>
<li><a href="#">Item #2</a></li>
<li><a href="#">Item #3</a></li>
<li><a href="#">Item #4</a></li>
</ul>
</div>
<script type="text/javascript">
window.onload = function() {
// 事件委托,即我们将click事件添加在<ul>元素上,再通过相应判断获得事件源
document.getElementById("list").addEventListener("click", function(e) {
if(e.target && e.target.nodeName.toLowerCase() == "a") {
console.log(e.target.text);
}
});
}
</script>
</body>
</html>
参考网址:
http://learn.jquery.com/events/event-delegation/
https://www.w3.org/TR/DOM-Level-2-Events/events.html