Определение индекса элемента списка - что лучше?

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

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. Есть ли какие-то очень плохие последствия от следования первому методу?

Первый метод не работает в браузерах, которые обрабатывают пробелы как текстовые узлы. Вы действительно не объясняете, почему вас волнует показатель, поэтому я не собираюсь размышлять о том, есть ли лучшие решения.

Shog9 15.11.2008 18:46
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
3 864
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

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

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

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

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

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

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

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

Другие вопросы по теме