一、事件委托,就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
为什么要用事件委托
一、在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断地与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间。如果用事件委托,就会将所有的操作放到js程序里面,只对它的父级(如果只有一个父级)这一个对象进行操作,与dom的操作就只需要交互一次,这样就能大大地减少dom的交互次数,提高性能。
事件委托的优点
一、事件委托的优点:
- 管理的函数变少了。不需要为每个元素都添加监听函数。对于同一个父节点下面类似的子元素,可以通过委托给父元素的监听函数来处理事件。
- 可以方便地动态添加和修改元素,不需要因为元素的改变而修改事件绑定。
- JavaScript和DOM节点之间的关联变少了,这样也就减少了因循环引用而带来的内存泄漏发生的概率。
事件真实发生的位置
一、在处理程序中,我们获取event.target以查看事件真实发生的位置并进行处理。
| 【示例】八卦图,在点击时高亮显示被点击的单元格
1、HTML```jsx
Bagua Chart: Direction, Element, Color, Meaning | ||
---|---|---|
Northwest Metal Silver Elders |
… | … |
2、event.target<br />(1)与其在每个<td>(可能有很多)分配给一个onclick处理程序:我们可以在<table>元素上设置一个“捕获所有”的处理程序。<br />(2)使用event.target来获取点击的元素并高亮显示它。```jsx
let selectedTd;
table.onclick = function(event) {
let target = event.target; // 在哪里点击的?
if (target.tagName != 'TD') return; // 不在 TD 上?那么我们就不会在意
highlight(target); // 高亮显示它
};
function highlight(td) {
if (selectedTd) { // 移除现有的高亮显示,如果有的话
selectedTd.classList.remove('highlight');
}
selectedTd = td;
selectedTd.classList.add('highlight'); // 高亮显示新的 td
}
3、上述代码的优缺点
(1)优点:此代码不会关注表格中有多少个单元格。我们可以随时动态添加/移除,高亮显示仍然有效。
(2)缺点:点击可能不是发生在上,而是发生在其内部。
4、改进后:在处理table.onclick中,我们应该接受这样的event.target,并确定该点击是否在内```jsx
table.onclick = function(event) {
let td = event.target.closest(‘td’); // (1)
if (!td) return; // (2)
if (!table.contains(td)) return; // (3)
highlight(td); // (4) };
(1)elem.closest(selector)方法返回与selector匹配的最近的祖先。在我们的例子中,我们从源元素开始向上寻找<td><br />(2)如果event.target不在任何<td>中,那么调用将立即返回,因为这里没有什么事儿可做。<br />(3)对于嵌套的表格,event.taget可能是一个<td>,但位于当前表格之外。因此我们需要检查它是否是我们表格中的<td><br />(4)如果是的话,就高亮显示它。 |
| --- |
| 【示例】标记中的行为:action in markup<br />编写一个有“保存”、“加载”和“搜索”等按钮的菜单。并且,这里有一个具有save、load和search等方法的对象<br />1、方法1:为每个按钮分配一个单独的处理程序<br />2、方法2:<br />(1)为整个菜单添加一个处理程序,并为具有方法调用的按钮添加data-action特性(attribute)```jsx
<button data-action="save">Click to Save</button>
(2)处理程序读取特性(attribute)并执行该方法```jsx
①我们也可以使用.action-save, .action-load类,但data-action特性(attribute)在语义上更好。我们也可以在CSS规则中使用它。<br />二、委托的好处<br />1、我们不需要编写代码来为每个按钮分配一个处理程序。只需要创建一个方法并将其放入标记(markup)中即可。<br />2、HTML结构非常灵活,我们可以随便添加/移除按钮。 |
| --- |
<a name="dInmJ"></a>
# “行为”模式
一、我们可以使用事件委托将“行为(behavior)”以声明方式添加到具有特殊特性(attribute)和类的元素中。<br />二、行为模式分为两个部分<br />1、我们将自定义特性添加到描述其行为的元素。<br />2、用文档范围级的处理程序追踪事件,如果事件发生在具有特定特征的元素上:则执行行为(action)<br />三、“行为”模式可以替代JavaScript的小片段。
| 【示例】行为:计数器<br />一、这里的特性data-counter给按钮添加了一个“点击增加”的行为```jsx
Counter: <input type="button" value="1" data-counter>
One more counter: <input type="button" value="2" data-counter>
<script>
// 如果点击按钮,它的值就会增加
document.addEventListener('click', function(event) {
if (event.target.dataset.counter != undefined) { // 如果这个特性存在...
event.target.value++;
}
});
</script>
1、我们可以根据需要使用data-counter特性,多少都可以。
2、我们可以随时向HTML添加新的特性。
3、使用事件委托,我们属于对HTML进行了“扩展”,添加了描述新行为的特性。
二、对于文档级的处理程序,始终用的是addEventListener
1、我们将事件处理程序分配给document对象时,我们应该始终使用addEventListener,而不是document.on
| 【示例】行为:切换器
点击一个具有 data-toggle-id 特性的元素将显示/隐藏具有给定 id 的元素```jsx
``` | | —- |