原生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
        }
    }
}


複製代碼
相關文章
相關標籤/搜索