原生JS事件委托的应用

3,401 阅读2分钟

原生JS事件委托的应用

大晚上,等方案,年底了,顺便传一篇总结,主要是第三部分,事件委托的应用。

一、fragment的使用

  1. 元素增加或者刷新后,能否被原addeventLister监听到--> 不能;
  2. appengChild只能添加Dom元素,不能是文本形式的Dom;
  3. fragment不能直接通过innerHtml添加内容;
        var body = document.getElementById('body');
        var fragment = document.createDocumentFragment();
        for (var i = 0; i < 100; i++) {
            var btn = document.createElement('button');
            btn.id = i;
            btn.className = 'btn';
            btn.type = 'button';
            btn.innerText = '按钮'
            fragment.appendChild(btn);
        }
        body.appendChild(fragment);


二、事件委托提升性能或者优化代码结构

参考:javascript事件监听与事件委托

  1. 给body或者Ul等父元素绑定click事件,实现事件的委托 ,比为每一个button绑定点击事件性能更加提升,也为新增元素后的,不再需要额外绑定监听事件,注意需要配合matches等api使用更佳。nice!

    var date2 = new Date();
    body.addEventListener('click', function(e) {
        var element = e.target;
        if (element.className == 'btn') {
            console.log(element.id);
        }
    })
    var date3 = new Date();

三、具体应用

一、场景

  1. 因为最近在做web的客服项目中,对话列表会不断接入新的客户,如果每接入一个客户就生成一个li,进行一个新的监听,代码结构就特别不好,所以通过事件委托,来抽离函数工作,极大的优化了代码结构;
  2. 需要在对话列表里边的每一个Li元素里边的一些小div做一些功能,需要用到对话列表上的特定数据,不如将这些数据全部绑定到li元素上,每次内部div的交互动作,都冒泡到父元素Li上,来获取所需要的数据;

二、简单的函数封装

    /**
 * @description: 事件委托
 * @parentFeature 父节点内监听
 * @currentFeature 目标节点的特征 
 * @path e.paht
 * @return: boolean
 */
function delegation(parentFeature, targetFeature, path) {

    for (var i = 0, length = path.length; i < length; i++) {
        var item = path[i];
        if (!item.nodeName) {
            // 当节点为document或者window的时候,nodeName为undefined
            return false
        }
        if (item.matches(targetFeature)) {
            //    当paht链上节点符合目标特征
            console.log(item)
            return true
        }

        if (item.matches(parentFeature)) {
            // 往上找到了监听的父节点
            return false
        }
    }
}



/**
 * @description:  获取元素上的状态消息
 * @infoTargetFeature: 所要获取消息上的元素
 * @infoName: 所需要获取的父元素的属性名
 * @return: 状态信息
 */
// 事件委托成功,并且继续寻找,获取li元素上的数据
function getLiInfo(parentFeature, targetFeature, path, infoTargetFeature, infoName) {

    for (var i = 0, length = path.length; i < length; i++) {
        var item = path[i];
        if (!item.nodeName || item.nodeName=="#document") {
            // 当节点为document或者window的时候,nodeName为undefined
            return false
        }
        // console.log(JSON.stringify(item))  //{} 空对象

        if (item.matches(targetFeature)) {
            //    当path链上节点符合目标特征
            var maxLength = 10;
            var parentEle = item.parentNode;
            var info = true
            for (var i = 0; i < maxLength; i++) {
                // 当往上寻找父元素,直到找到设定父元素的所需要的状态信息,并返回
                if (parentEle.matches(infoTargetFeature)) {
                    console.log(parentEle.dataset)
                    info = parentEle.dataset[infoName];
                    console.log(info)
                    return info
                }
                parentEle = parentEle.parentNode
            }
            return true
        }

        if (item.matches(parentFeature)) {
            // 往上找到了监听的父节点
            return false
        }
    }
}