JavaScript 中的事件委托

Posted by cl9000 on May 18, 2020

万物皆有其美,但并非人人都能发现。——<安迪.沃霍尔>

事件委托是一个功能强大的事件处理概念。如果您正在使用jQuery,您可能知道它是jQuery.on()。由于我不再使用jQuery,所以我必须自己编写一个类似的函数。如果您想知道代码是什么样子的?

什么是事件委托

对于事件委托,我们只设置一个事件处理函数,然后该函数分析事件的目标元素并执行预期的处理函数。
这样我们就有了更好的代码可读性和性能改进。当内容动态更改时,不需要设置新的事件处理程序。
这对于列表或表格来说非常方便。

在jQuery代码中,我们可以调用

1
jQuery('#list').on('click', '.item', eventHandler)

例如: 有一个包含100个项目的列表。我们希望在单击列表项时调用eventHandler函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul id="list">
<li>1</li>
<li>2</li>
<li>...</li>
<li>100</li>
</ul>
<script>
var list = document.getElementById('list');
list.addEventListener('click', function eventHandler(event) {
// one item in the list was clicked
console.log(event.target); // this is that item
event.target.style.backgroundColor = '#f00';
});
</script>

这只是事件冒泡,不是吗?

第一个例子不是很壮观。它只使用事件冒泡,这在JavaScript中是很常见的。

但是我们可以看的更远些。如果仅某些特定元素应触发我们的eventHandler功能怎么办?这也是可能的。使用jQuery时,代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul id="list">
<li class="yes">1</li>
<li class="no">2</li>
<li class="no">3</li>
<li>...</li>
<li class="yes">100</li>
</ul>
<script>
$('#list').on('click', '.yes', function eventHandler(e) {
// this function is only called,
// when a list item with 'yes' class is called
console.log(e.target); // this is the clicked list item
});
</script>

不使用 jQuery 怎么办?

看下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<ul id="list">
<li class="yes">1</li>
<li class="no">2</li>
<li class="no">3</li>
<li>...</li>
<li class="yes">100</li>
</ul>
<script>
function on(elSelector, eventName, selector, fn) {
var element = document.querySelector(elSelector);
element.addEventListener(eventName, function(event) {
var possibleTargets = element.querySelectorAll(selector);
var target = event.target;
for (var i = 0, l = possibleTargets.length; i < l; i++) {
var el = target;
var p = possibleTargets[i];
while(el && el !== element) {
if (el === p) {
return fn.call(p, event);
}
el = el.parentNode;
}
}
});
}

on('#list', 'click', '.yes', function(e) {
// this function is only called, when a list item with 'yes' class is called
console.log(e.target); // this is the clicked list item
});
</script>

演示如下

浏览器支持

此代码使用两个核心 DOM API 调用 Element.addEventListenerElement.querySelectorAll。每个现代浏览器和 IE9+ 均支持这些功能。

参考

关注【公众号】,了解更多。

向文本区域添加标签支持



支付宝打赏 微信打赏

赞赏一下 坚持原创技术分享,您的支持将鼓励我继续创作!