原生JS事件委托的应用

原生JS事件委托的应用

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

1、fragment的使用

  1. 元素增长或者刷新后,可否被原addeventLister监听到--> 不能;
  2. 前者页面只重排一次,后者页面重排了100次;因此若遇到大模块添加dom时,最好使用fragment;
  3. appengChild只能添加Dom元素,不能是文本形式的Dom;
  4. 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);


复制代码

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

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

  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. 常规为元素绑定事件,并经过闭包来处理(只有一项绑定了点击事件)
var btn = document.querySelectorAll('.btn');
    var date1 = new Date();
    for (var i = 0; i < btn.length; i++) {
        (function(i) {
            btn[i].addEventListener('click', function() {
                console.log(i);
            });
        })(i)
    }
复制代码

具体应用

1、场景

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

2、简单的函数封装

/** * @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
        }
    }
}


复制代码
相关文章
相关标签/搜索