• 作者:老汪软件技巧
  • 发表时间:2024-09-05 21:02
  • 浏览量:

前言

在前端开发中,事件处理是非常重要的一部分。随着应用变得越来越复杂,页面上的元素数量也会逐渐增加。如果为每一个元素单独绑定事件监听器,不仅会让代码变得冗长,还会导致性能下降。这时,事件代理(Event Delegation)就成为了一种优化方案。本文将通过几个具体的示例来解释什么是事件代理,并帮助理解其工作原理。

什么是事件代理?

事件代理是一种在父级元素上监听事件,从而间接管理子级元素事件的技术。这种方法利用了事件冒泡的原理:事件会从最深的节点开始逐级向上冒泡,直到达到最顶层的节点。通过在较高级别的元素上监听事件,我们可以捕获发生在任何子元素上的事件,而无需为每个子元素单独绑定事件处理器。

事件代理的好处减少事件处理器:只需要为一个父元素绑定事件处理器,而不是为每一个子元素。易于维护:当子元素动态增加或减少时,不需要重新绑定事件。性能提升:减少事件处理器的数量可以降低内存消耗和提高性能。事件代理的工作原理

事件代理的关键在于理解事件冒泡机制。当用户点击页面上的某个元素时,事件会首先在这个元素上触发,然后向上冒泡,直到到达文档的根节点。我们可以利用这一点,在较高层级的元素上监听事件,然后通过事件对象来判断实际触发事件的元素。

正文

让我们通过几个具体的例子来更好地理解事件代理的实现方式。

示例一:为列表项单独绑定事件

场景:如果有一个列表,里面有几十个标签,让你点击哪个就显示哪个的内容你会怎么做?诶,这时我们会想,这还不简单吗,每个都绑定点击事件咯,再把它标签的内容展示出来不就好了,下面代码就是如此:

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件代理示例title>
head>
<body>
    <ul>
        <li>1li>
        <li>2li>
        <li>3li>
    ul>
         
    <script>
        let lis = document.querySelectorAll('li');
        lis.forEach((li, i) => {
            li.addEventListener('click', function () {
                console.log(this.innerText);
            });
        });
    script>
body>
html>

这里简略点就写了三个,那那么多每个都绑定那不是太麻烦嘛,可不可以简单一点的,诶,还真有,下面为用了事件代理的升级版:

示例二:使用事件代理为列表项绑定事件

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件代理示例title>
head>
<body>
    <ul>
        <li>1li>
        <li>2li>
        <li>3li>
    ul>
         
    <script>
        let ul=document.querySelector('ul')
        ul.addEventListener('click',function(e){
            console.log(e.target.innerText)
        })
    script>
body>
html>

效果:

可以看到,我们点击不同的一样可以实现我们想要的效果,我们仅在

用处: 我们看这个图片:

我们点击js检测页面空闲这个大的部分是不是会进入到这个页面,那如果我们点击点赞的部分是不是会变得高亮呀,如果我们不设置上面的方法,那么是不是点击点赞部分就会冒泡触发外面大的部分进行跳转呀,所有这个方法还是很重要的。

示例四:使用onclick多次绑定事件

<body>
    <div id="grand" onclick="handleGrand()" onclick="handleGrand()">
        <div id="parent" onclick="handleParent()">
            <div id="child">
            div>
        div>
    div>
    <script>
        function handleGrand(){
            console.log("grand1");
        }
        function handleGrand(){
            console.log("grand2");
        }
        function handleParent(){
            console.log("parent");
            
        }
    script>
    
    // 点击parent部分,打印:parent,grand2
body>

我们只改变body里面的代码,在这个示例中,我们尝试在 grand 元素上使用 onclick 属性多次绑定事件处理器。然而,由于 onclick 是 DOM0 的方法,只能绑定一个事件处理器,第二个 handleGrand 函数会覆盖第一个,这种方式不如使用 addEventListener 方便和灵活。

示例五:输入框的焦点和失焦事件

html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <input type="text" name="" id="input">
    <script>
        let input = document.getElementById('input');
        input.addEventListener('focus', function(e) {
            console.log('focus');
        })
        input.addEventListener('blur', function(e) {
            console.log('blur');
            
        })
    script>
body>
html>

在这个示例中,我们为输入框绑定了焦点focus和失焦blur事件。这两种事件不属于事件冒泡的一部分,因此不能通过事件代理来实现。

总结

js中的事件流:

1.捕获阶段 --- 事件从window处往目标处传播

2.目标阶段 --- 在目标处触发事件

3.冒泡阶段 --- 事件从目标处往window处传播,这个就是冒泡阶段

重点:js 中的事件默认在冒泡阶段触发

DOM0 vs DOM2

事件代理:把元素身上需要响应的事件,委托到另一个元素(父元素)上

无事件件流:1.focus2.blur

本文到此就结束了,感谢你的阅读,希望对你有所帮助!