识别列表项索引 - 这是一种更好的方法吗?

时间:2008-11-15 15:01:00

标签: javascript html dom

我需要从列表中选择列表项,然后执行添加事件处理程序等操作。我可以想到两种方法。

HTML:

    <ul id="list">
       <li id="listItem-0"> first item </li>
       <li id="listItem-1"> second item </li> 
       <li id="listItem-2"> third item </li> 
    </ul>
  1. 使用ID -

    for(i=0;i<3;i++)
    {
       document.getElementById("listItem-"+i).addEventListener("click",foo,false);
    }
    
  2. 使用childNodes属性 -

    for(i=0;i<3;i++)
    {
      document.getElementById("list").childNodes[i]
         .addEventListener("click",foo,false);
    }
    
  3. 我使用第一种方法的原因是在函数foo中,如果我想要项目在列表中的索引,我可以通过拆分id来实现 -

        function foo()
        {
          tempArr = this.id.split('-');      
          index = tempArr[tempArr.length-1]; // the last element in the array
        }
    

    我想不出使用第二种方法的方法,即不使用id命名方案。

    问题:

    1. 如何使用第二种方法或更好的方法获取索引
    2. 遵循第一种方法会有一些非常糟糕的影响吗?

4 个答案:

答案 0 :(得分:3)

通过向包含元素(无序列表)添加单个事件处理程序并利用事件冒泡的概念,可以避免向每个列表项添加事件处理程序。在此单个事件处理程序中,您可以使用事件对象的属性来确定单击的内容。

您似乎想要将数组中的数据映射到列表项。从列表项ID中解析出数组索引可以工作,另一种方法是将列表项上的“键”值存储为expando,并使用javascript对象属性对数据进行查找。

部分示例:

<li key="myKey">

//oData is a object (eg. var oData = {};) that has been populated with properties
//whose value is the desired data (eg. oData["myKey"] = 123;)

alert(oData[event.srcElement.key]); // alerts 123

就你所展示的第一种技术的不良影响而言,一个不好的结果是,对于许多列表项,你最终定义了许多事件处理程序,这在某些时候会对性能产生影响。

另请注意,通过省略“i”的var关键字,可能会无意中在循环中创建全局变量。

答案 1 :(得分:1)

如果您选择使用jQuery,它就像以下一样简单:

$('ul#list li').click(function () {
    var i = this.id.split('-').pop();
    alert( i );
});

答案 2 :(得分:1)

也许类似于:

var lis = document.getElementById("list").getElementsByTagName("li");

for (var i = 0, li; li = lis[i]; ++i) {
  li.addEventListener("click", (function(pos) {
    return function() {
      alert(pos);
    };
  })(i), false);
}

或者,从J cs回答和custom data attributes获得一些灵感:

var lis = document.getElementById("list").getElementsByTagName("li");

for (var i = 0, li; li = lis[i]; ++i) {
  li.setAttribute("data-index", i); // Or whatever value you want...
  li.addEventListener("click", function() {
    alert(this.getAttribute("data-index"));
 }, false);
}

答案 3 :(得分:0)

如前所述,如果要检索li列表,则应在ul上使用getElementsByTagName,因为childNodes可能会检索一些文本节点以及li节点。

现在,如果你需要在事件处理程序中使用索引,你最好直接使用闭包来重用事件处理程序中的循环变量。

var lis = document.getElementById("list").getElementsByTagName("li");

for( var i = 0, l = lis.length; i < l; ++i )
{
    (function(){

        // As a new variable will be created for each loop, 
        // you can use it in your event handler  
        var li = lis[i]; 

        li.addEventListener("click", function() 
        {
            li.className = "clicked";

        }, false);

    })();
}

但您可以考虑为此目的进行事件委托。您只需将事件处理程序附加到父元素,并使用目标属性查找单击的元素。

document.getElementById("list").addEventListener("click", function(event)
{
    var li = event.target;
    if( li.nodeName.toLowerCase() == "li" )
    {
        ...
    }
}, false);