纯 js 中的可折叠列表优化

Collapsable list optimisation in pure js

本文关键字:列表 优化 可折叠 js      更新时间:2023-09-26

我正在构建一个可折叠的列表,在我试图优化我的代码时,我发现自己做了一些吐出错误的东西,但由于某种原因仍然以某种方式工作。

旧代码:http://jsfiddle.net/3pmcrqmj/

function addEvent(element, myEvent, fnc) {
return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false));
}
var list = document.getElementById('list');
var items = list.getElementsByTagName('ul');
var items2 = list.getElementsByTagName('li');
for(var i = 0; len = items.length, i < len ; i++){
    items[i].parentNode.setAttribute('class','collapse');
    addEvent(items[i].parentNode, 'click', function(event) {
        event = event || window.event;
        event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
        if(this.getAttribute('class')==='collapse'){
            this.setAttribute('class','expand');
        } else {
            this.removeAttribute('class');
            var temp = this;
            setTimeout(function(){
                temp.setAttribute('class','collapse');
            },200);
        }
    });
}

我的修复尝试:http://jsfiddle.net/3pmcrqmj/1/

function addEvent(element, myEvent, fnc) {
return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false));
}
var list = document.getElementById('list');
var items = list.getElementsByTagName('ul');
var items2 = list.getElementsByTagName('li');
for(var i = 0; len = items.length, i < len ; i++){
    items[i].parentNode.setAttribute('class','collapse');
}
addEvent(list, 'click', function(event) {
    for(var i = 0; len = items.length, i < len ; i++){
        event = event || window.event;
        event.stopPropagation ? event.stopPropagation() : (event.cancelBubble=true);
        if(event.target.getAttribute('class')==='collapse'){
            event.target.setAttribute('class','expand');
            target.setAttribute('class','expand');
        } else {
            event.target.setAttribute('class','collapse');
            target.setAttribute('class','collapse');
        }
    }
});

如何正确冒泡,以便不必在每个列表项上插入事件侦听器?

通过检查单击元素的nodeName(== li)和子<li>-元素的存在来重写处理程序,因此它仅作用于这些元素:

addEvent(list, 'click', function (e) {
     e = e || window.event;
     var from = e.target || e.srcElement;
     if (!/^li$/i.test(from.nodeName) ||
         !from.querySelectorAll('li').length) {return true;}
     var expand = /collapse/i.test(from.className || '');
     from.setAttribute('class', expand ? 'expand' : 'collapse');
});

这是你重写的jsFiddle