JQuery事件委托使用及原生JS实现同等功能 - 解决动态插入的数据事件监听

当我们在一个固定容器(如 <ul>)中动态加载新的元素(如 <li>)时,直接对新加载的元素绑定事件可能无效。这是因为,页面加载时并没有这些新添加的 <li> 元素,它们是在页面加载后才被动态插入的,因此无法用普通的事件绑定来处理。此时,我们可以使用事件委托来解决问题。

事件委托的原理是:通过将事件绑定在父元素上,由父元素来监听子元素的事件。当子元素被点击时,事件会“冒泡”到父元素,父元素处理这个事件。

示例 HTML 结构

<ul id="wrap">
    <li>item1</li>
    <li>item2</li>
    <li>item3</li>
    <li>item4</li>
    <li>item5</li>
</ul>
<button id="addBtn">添加新的项</button>

这个例子中,我们有一个固定的 ul 容器,里面有一些初始的 li 项。点击按钮时,会动态添加新的 li

1. 普通事件绑定

普通事件绑定直接绑定在已有的 li 元素上,对于页面加载时已经存在的元素是有效的,但对动态添加的元素无效。

$('li').click(function(){
    $(this).css('background', '#D4DFE6');
});

问题:这种方式只能对当前已有的 li 进行操作,无法处理后续动态添加的 li

2. 动态添加 DOM 节点

我们通过点击按钮动态添加新的 li 元素到 ul 末尾。

$('#addBtn').click(function(){
    $('#wrap').append( $('<li>item'+ ($('li').length + 1) +'</li>') );
});

3. 事件委托解决方案

为了对动态添加的 li 元素也能够绑定点击事件,我们可以使用事件委托

3.1 使用 jQuery 的 delegate 方法(旧版 jQuery)

delegate 是早期 jQuery 提供的事件委托方式,已被更现代的 on 方法取代。下面是 delegate 的实现:

$('#wrap').delegate('li', 'click', function(ev){
    // this 指向被点击的 li 元素
    $(this).css('background', '#D4DFE6');

    // 找到父级 ul#wrap,并为其设置红色边框
    $(ev.delegateTarget).css('border', '2px solid #f00');
});

解释

  • ev.delegateTarget 是指向事件代理的目标,即父元素 ul

3.2 使用 jQuery 的 on 方法(推荐方式)

on 是 jQuery 1.7 版本之后的标准事件绑定方法,支持事件委托。推荐使用 on 代替 delegate

$('#wrap').on('click', 'li', function(ev) {
    // this 指向被点击的 li 元素
    $(this).css('background', '#D4DFE6');

    // 找到父级 ul#wrap,并为其设置红色边框
    $(ev.delegateTarget).css('border', '2px solid #f00');
});

解释

  • 事件绑定在 #wrap 上,当其子元素 li 被点击时,事件冒泡到 #wrap,由 #wrap 处理事件。
  • 事件委托的核心是将事件绑定在父元素上,而不是直接绑定在子元素上。

3.3 使用原生 JavaScript 实现事件委托

如果你不想依赖 jQuery,原生 JavaScript 同样可以实现事件委托。

var _wrap = document.getElementById('wrap');
_wrap.addEventListener('click', function(ev){
    var ev = ev || event;  // 兼容 IE
    if (ev.target.nodeName === 'LI') {  // 判断点击的元素是否是 li
        ev.target.style.background = '#8EC0E4';  // 修改背景色
        console.log(ev.target.innerHTML);  // 输出 li 内容
    }

    // 设置父元素 ul 的边框
    this.style.border = '2px solid #f00';
});

解释

  • ev.target 是指事件触发的实际元素,通过判断它是否是 LI 元素来执行操作。
  • this 仍然指向事件监听的目标,即 ul#wrap

4. 结论

通过事件委托,我们能够轻松解决动态加载元素无法直接绑定事件的问题。推荐使用 jQuery 的 on 方法或原生 JavaScript 的 addEventListener 来实现这一功能。总结如下:

  • 普通事件绑定 只对初始加载的元素有效,不适用于动态添加的元素。
  • 事件委托 是解决动态元素事件绑定问题的最佳方式,可以通过 jQuery 的 on 或原生 JavaScript 实现。
  • 无论是 jQuery 还是原生 JavaScript,关键点都是将事件绑定在父容器上,而不是直接绑定在子元素上。

通过这些方法,我们可以确保无论元素是初始加载还是动态添加,都能正确处理事件。

完整的代码示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件委托示例</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
    <ul id="wrap">
        <li>item1</li>
        <li>item2</li>
        <li>item3</li>
        <li>item4</li>
        <li>item5</li>
    </ul>
    <button id="addBtn">添加新的项</button>

    <script>
        // 动态添加 li 元素
        $('#addBtn').click(function() {
            $('#wrap').append( $('<li>item'+ ($('li').length + 1) +'</li>') );
        });

        // 事件委托 - jQuery 的 on 方法
        $('#wrap').on('click', 'li', function(ev) {
            $(this).css('background', '#D4DFE6');
            $(ev.delegateTarget).css('border', '2px solid #f00');
        });
    </script>
</body>
</html>

希望这篇整理后的博客内容能够让你更容易理解事件委托以及如何解决动态加载元素的事件绑定问题。

标签: Javascript, JQuery

相关文章

在JavaScript或Vue中屏蔽所有报错信息

在 JavaScript 或 Vue 中,如果你想屏蔽所有 JavaScript 报错,可以通过捕获全局的错误事件来实现。需要注意的是,尽量避免屏蔽所有错误,因为这可能会掩盖一些实际问题,影响调...

浏览器的开发工具中有个jsContext是什么

什么是 jsContext?在JavaScript中,jsContext 并不是一个官方的术语或概念。通常情况下,开发者可能会提到 context 这个词,它通常指的是执行上下文(Executi...

在HTML中为 h1-h6 标签添加序号及颜色背景色块

在HTML结构中,h1 到 h6 是常见的标题标签,通常我们会希望对这些标题进行标注或编号,使其更具层次感。在这篇文章中,我将向您展示如何通过纯JavaScript自动为 h1 到 h6 标签添...

VUE倒计时组件

常用于发送短信、邮件后1分钟倒计时,倒计时结束后又可以再次点击vue组件封装:<template> <div class="timer-btn">...

图片Base64编码

CSR生成

图片无损放大

图片占位符

Excel拆分文件