Определение индекса элемента списка - какой подход лучше? - PullRequest
0 голосов
/ 15 ноября 2008

Мне нужно выбрать элементы списка из списка, а затем выполнить такие операции, как добавление к ним обработчиков событий. Я могу придумать два способа сделать это.

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. Использование идентификаторов-

    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);
    }
    

Причина, по которой я использую первый подход, заключается в том, что в функции foo, если мне нужен индекс, по которому элемент находится в списке, я могу сделать это, разделив идентификатор -

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

Я не могу придумать, как это сделать, используя второй метод, то есть без использования схемы именования идентификаторов.

Вопросы:

  1. Как получить индекс, используя второй метод или любой другой лучший метод
  2. Есть ли очень плохие последствия следования первому методу?

Ответы [ 4 ]

3 голосов
/ 15 ноября 2008

Вы можете избежать добавления обработчиков событий к каждому элементу списка, добавив отдельный обработчик событий в содержащий элемент (неупорядоченный список) и используя концепцию всплытия событий. В этом отдельном обработчике событий вы можете использовать свойства объекта события, чтобы определить, на что щелкнули.

Похоже, что вы хотите отобразить данные в массиве для списка элементов. Хотя разбор индекса массива по идентификатору элемента списка будет работать, другой подход заключается в сохранении значения «ключа» в элементе списка в качестве эксплоона и использовании свойств объекта 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

Что касается плохих эффектов первой техники, которую вы показали, один плохой эффект состоит в том, что со многими элементами списка вы в конечном итоге определяете множество обработчиков событий, что в какой-то момент может повлиять на производительность.

Также обратите внимание, что вы можете непреднамеренно создать глобальную переменную в ваших циклах, пропустив ключевое слово var для «i».

1 голос
/ 15 ноября 2008

Может быть, что-то похожее на:

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 и пользовательских атрибутов данных :

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);
}
1 голос
/ 15 ноября 2008

Если вы решите использовать jQuery, все будет просто:

$('ul#list li').click(function () {
    var i = this.id.split('-').pop();
    alert( i );
});
0 голосов
/ 16 ноября 2008

Как указывалось ранее, если вы хотите получить список li, вы должны использовать getElementsByTagName на вашем ul, потому что 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);

    })();
}

Но вы можете рассмотреть делегирование событий для этой цели. Вам нужно только прикрепить обработчик событий к родительскому элементу и найти элемент, по которому щелкнули, используя атрибут target.

document.getElementById("list").addEventListener("click", function(event)
{
    var li = event.target;
    if( li.nodeName.toLowerCase() == "li" )
    {
        ...
    }
}, false);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...