利用事件代理获取事件中多个标签图片中某一个

14次阅读

共计 1485 个字符,预计需要花费 4 分钟才能阅读完成。

场景:一个页面中的导航栏 / 图片下拉框,具有多个相同的标签节点,可以获取点击的某一个,并封装对应的方法函数(不考虑 IE)
需要考虑的步骤:
(1)事件代理的原理(事件冒泡)
(2)函数中需要考虑的几点(默认行为,this 指向)


1. 事件捕获和事件冒泡
DOM 是一种树形结构,事件会在元素结点和根结点之间传递,途经的结点会收到该事件,传递过程可以称为事件流。
事件流分为三个阶段:

  • 捕获阶段
  • 目标阶段
  • 冒泡阶段

事件冒泡会从当前触发的事件目标一级一级往上传递,依次触发,直到 document 为止。
事件捕获会从 document 开始触发,一级一级往下传递,依次触发,直到真正事件目标为止。
window->document->HTML->body-> 父元素 -> 子元素

2. 事件代理
(1)原理:事件冒泡机制。当子结点触发事件时,事件流会向父节点传播,并触发父节点上的事件。
(2)优点:

  • 代码简洁,当动态增加结点时,无需做额外操作
  • 减少绑定注册事件,减少浏览器内存消耗

3. 函数实现
(1)实现一次事件冒泡

  <div id="para">
        <ul id="contain">
            <li id="p1"> 标签 1 </li>
            <li id="p2"> 标签 2 </li>
            <li id="p3"> 标签 3 </li>
        </ul>
    </div>
    


   /*
    *
    * 事件冒泡
    *
    */
    function bindEvent(elem, type, fn) {elem.addEventListener(type, fn);
    }
    var paras = document.getElementById('para')
    var contains = document.getElementById('contain')
    var p1s = document.getElementById('p1')
    console.log(paras, contains, p1s)
    bindEvent(p1s, 'click', function(e) {e.preventDefault()
        // 阻止事件冒泡 e.stopPropagation() e.cancelBubble = true IE
        console.log('p')
    })
    bindEvent(paras, 'click', function(e) {console.log('para')
    })


可以看到,当点击标签的时候,结点的父元素也触发了对应的方法。
(2)实现事件代理

   /*
    *
    * 事件代理
    *
    */
    function eventProxy(elem, type, proxyElem, fn) {if(fn === null) { // 不使用事件代理
            fn = proxyElem;
            proxyElem = null;
        }
        elem.addEventListener(type, function(e) {
            var target;
            if(proxyElem) { // 使用事件代理的情况
                target = e.target;
                console.log(target)
                if (target.matches(proxyElem)) {fn.call(target, e); // 改变函数 this 执行上下文到目标结点
                }
            } else { // 不使用事件代理的情况
                fn(e);
            }
        })
    }
    var proxyContainer = document.getElementById('proxy');
    eventProxy(proxyContainer, 'click', 'a' , function(e) {e.preventDefault();
        console.log(this.innerHTML); // 获取当前结点信息
    })


可以看到,通过事件代理的方式,将事件绑定在父节点上,并可以区分被点击分子节点的信息。

正文完
 0