事件委托(事件代理)

        事件委托是一种利用事件冒泡机制来简化事件处理的技术,它并不是针对“不具有事件冒泡的属性”,而是针对事件冒泡的一种应用。 其基本思想是将事件处理程序绑定到父元素上,然后利用事件冒泡的机制来处理子元素上的事件。当子元素上的事件被触发时,事件会冒泡到父元素,然后可以在父元素上统一处理这些事件,而不需要为每个子元素单独绑定事件处理程序。 这种技术可以减少事件处理程序的数量,提高性能,并且对于动态生成的子元素也非常有用

事件代理有以下几个优点:

  1. 减少内存消耗:当有大量子元素需要绑定事件时,使用事件代理可以减少内存消耗,因为只需要为父元素绑定一个事件处理程序。
  2. 动态元素处理:对于动态添加的元素,使用事件代理可以确保这些元素上的事件也能被处理,而不需要重新绑定事件处理程序。

注意:

        事件代理是一种利用事件冒泡机制来简化事件处理的技术,它可以应用于所有支持事件冒泡的事件,而不仅仅是针对具有事件冒泡属性的事件。

以下常用的 HTML 属性支持事件冒泡:

        在 HTML 中,事件冒泡是一种事件流模型,即事件在从最特定的元素(通常是文档中的某个元素)开始触发,然后沿着 DOM 树逐级向上冒泡,直到根节点。在 JavaScript 中,通过 addEventListener 方法添加的事件处理函数默认使用事件冒泡模型。

  • - onclick
  • - ondblclick
  • - onmousedown
  • - onmouseup
  • - onmouseenter
  • - onmouseleave
  • - onmousemove
  • - onmouseout
  • - onmouseover
  • - onkeydown
  • - onkeyup
  • - onkeypress
  • - onsubmit
  • - onreset

        需要注意的是,并不是所有事件都支持冒泡,例如focusblur事件就不支持冒泡。在使用事件代理时,需要注意事件是否支持冒泡,以确保事件代理的正确应用。

以下是一个事件委托最简单的例子:

        假设我们有一个列表,其中的每个列表项都有一个删除按钮,我们希望点击删除按钮时能够删除相应的列表项。我们可以使用事件委托来实现这个功能。

```html
<ul id="item-list">
  <li>Item 1 <button class="delete-btn">Delete</button></li>
  <li>Item 2 <button class="delete-btn">Delete</button></li>
  <li>Item 3 <button class="delete-btn">Delete</button></li>
  <li>Item 4 <button class="delete-btn">Delete</button></li>
</ul>
```

```javascript
// 获取父元素
var list = document.getElementById('item-list');

// 添加事件监听器到父元素
list.addEventListener('click', function(event) {
  // 检查点击的是否是删除按钮
  if (event.target.classList.contains('delete-btn')) {
    // 找到要删除的列表项并进行删除
    var listItem = event.target.parentNode;
    list.removeChild(listItem);
  }
});
```

        在这个例子中,我们将事件处理程序绑定到父元素ul上,而不是将事件处理程序绑定到每个按钮上。当点击任何一个删除按钮时,事件会冒泡到ul元素,我们在事件处理程序中检查点击的是否是删除按钮,然后找到要删除的列表项并进行删除。这样就实现了事件委托,减少了事件处理程序的数量,提高了性能。另外,如果以后动态添加了新的列表项,也无需重新绑定事件处理程序,事件委托会自动处理新元素的事件。

应用场景:

事件委托可以应用于许多场景,以下是一些常见的应用场景,并且我将为每个场景提供一个简单的JavaScript代码示例。

1. 列表/表格中的操作
   - 场景:处理列表或表格中的操作,比如点击列表项的删除按钮。
 代码见上面例子

2. 动态生成的元素
   - 场景:处理通过JavaScript动态生成的元素的事件,比如通过Ajax加载的内容或通过React动态渲染的组件。
   - 代码示例:

```javascript
// 假设通过Ajax加载的评论列表
function loadComments() {
  // 假设通过Ajax获取到了评论数据
  let comments = getCommentsFromServer();
  let commentList = document.getElementById('commentList');
  commentList.innerHTML = ''; // 清空列表

  comments.forEach(function(comment) {
    let commentItem = document.createElement('div');
    commentItem.innerHTML = comment.content + ' <button class="like-btn">Like</button>';
    commentList.appendChild(commentItem);
  });
}

document.getElementById('commentList').addEventListener('click', function(event) {
  if (event.target.classList.contains('like-btn')) {
    // 处理点赞操作
    console.log('Liked comment:', event.target.parentNode.textContent);
  }
});

// 调用加载评论的函数
loadComments();
```

3. 全局事件处理
   - 场景:处理全局的键盘事件、鼠标事件等。
   - 代码示例:

```javascript
document.addEventListener('keydown', function(event) {
  if (event.key === 'Escape') {
    // 处理按下Escape键的操作
    console.log('Escape key pressed');
  }
});

document.addEventListener('click', function(event) {
  // 处理全局的点击事件
  console.log('Clicked on', event.target);
});
```

4. 表单验证
   - 场景:实时验证表单输入、处理提交按钮的点击事件。
   - 代码示例:

```html
<form id="myForm">
  <input type="text" id="username" placeholder="Username">
  <input type="password" id="password" placeholder="Password">
  <button type="submit">Submit</button>
</form>

<script>
  document.getElementById('myForm').addEventListener('input', function(event) {
    // 实时验证输入
    if (event.target.value.length < 6) {
      event.target.style.borderColor = 'red';
    } else {
      event.target.style.borderColor = 'green';
    }
  });

  document.getElementById('myForm').addEventListener('submit', function(event) {
    event.preventDefault(); // 阻止默认提交行为
    // 处理表单提交
    console.log('Form submitted');
  });
</script>
```

5. 单页应用中的路由切换
   - 场景:处理单页应用中页面路由切换后新元素的事件。
   - 代码示例:

```javascript
// 假设在单页应用中,通过路由切换加载了新的组件
function loadNewComponent() {
  // 加载新组件的代码
  let newComponent = document.createElement('div');
  newComponent.innerHTML = '<button class="new-btn">New Button</button>';
  document.getElementById('app').appendChild(newComponent);
}

document.getElementById('app').addEventListener('click', function(event) {
  if (event.target.classList.contains('new-btn')) {
    // 处理新组件中的按钮点击事件
    console.log('Clicked on new button:', event.target);
  }
});

// 调用加载新组件的函数
loadNewComponent();
```
  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值