Не могу понять обработчик событий Javascript с кодом цикла for

Я пытаюсь изучить JavaScript и увидел код для изменения стиля css веб-страницы в зависимости от нажатия кнопки.

Я не могу понять, почему и как цикл for указывает, что кнопка ведьмы была нажата. Вот часть javascript:

var buttons = document.getElementsByTagName("button");

var len = buttons.length;

for (i = 0; i < len; i++) {
  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

http://jsfiddle.net/qp9jwwq6/

Я посмотрел в сети и в школе w3, но они не объясняют этот код циклом for. Может ли кто-нибудь объяснить это мне?

Спасибо


person Christian Pineault    schedule 06.02.2015    source источник
comment
добавить прослушиватель кликов к каждому <button>, который устанавливает класс тела для текста кнопки   -  person Tomanow    schedule 07.02.2015


Ответы (3)


Давайте сломаем это.

Сначала нам нужно получить доступ к элементу DOM на странице, поэтому мы делаем это, используя метод самого document, который возвращает элемент, которым мы хотим манипулировать.

var buttons = document.getElementsByTagName("button");

Переменная buttons будет списком ВСЕХ кнопок на странице. Мы хотим что-то сделать со всеми ними, поэтому сначала кэшируем длину списка, т. е. подсчитываем, сколько кнопок у нас есть.

var len = buttons.length;

Затем мы в основном говорим: установите i равным 0 и увеличивайте его на единицу, пока он не будет равен количеству кнопок, которые у нас есть.

for (i = 0; i < len; i++) {

Теперь, чтобы получить доступ к одной кнопке из списка, нам нужно использовать обозначение скобок. Итак, buttons[0] — это первый элемент, buttons[1] — второй и т. д. Поскольку i начинается с 0, мы помещаем i в скобки, чтобы на каждой итерации он обращался к следующей кнопке в списке.

  buttons[i].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };
}

Это эквивалентно выполнению:

 buttons[0].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[1].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

 buttons[2].onclick = function() {
    var className = this.innerHTML.toLowerCase();
      document.body.className = className;
  };

// etc.

Но, конечно, это супер неэффективно, и мы можем не знать, сколько кнопок на странице. Итак, мы получаем там все кнопки, узнаем, сколько их, затем проходим по каждой кнопке и назначаем ей обработчик событий вместе с новым классом.

Теперь, взглянув на сам обработчик onclick, мы видим, что он сначала находит HTML внутри кнопки, по которой нажимают, преобразует его в строчные буквы и присваивает его переменной:

var className = this.innerHTML.toLowerCase();

Используя this, мы гарантируем, что каждая кнопка будет получать собственный innerHTML при нажатии. Мы не отслеживаем, какая кнопка какая, мы просто говорим каждой кнопке проверять свое собственное содержимое.

Затем он изменяет класс HTML-элемента body на то, что мы только что проанализировали.

document.body.className = className;

Итак, скажите, что у вас есть что-то вроде

<button>success</button>
<button>failure</button>
<button>warning</button>

Нажатие первой кнопки установит класс элемента <body> на success, нажатие второй кнопки установит его на failure, а третье — на warning.

person Aweary    schedule 06.02.2015

Первая строка сохраняет все кнопки в переменной с именем buttons. На самом деле это массив, так как на странице может быть несколько кнопок. Затем вы перебираете каждую кнопку и определяете функцию, которая должна выполняться при нажатии. Допустим, у вас есть 2 кнопки, тогда это будут кнопки [0] и кнопки [1], которые получают функцию.

person kukudas    schedule 06.02.2015

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

К ответу:

Цикл for не «указывает», какая кнопка была нажата. Вместо этого он перебирает каждый элемент кнопки на странице и присваивает точно такое же определение функции атрибуту onclick каждого элемента. Код, который запускается при нажатии определенного элемента кнопки (здесь я говорю о теле функции), назначает класс CSS элементу body, назначая document.body.className.

Ваш вопрос заключается в том, как функция узнает, какое имя класса назначить document.body.className. Функция получает имя класса из innerHTML элемента кнопки, который доступен как this.innerHTML (поскольку в обработчике событий this является ссылкой на элемент, для которого произошло инициирующее событие). HTML-элемент <button> немного особенный, хотя в целом это простая на вид кнопка, но он также является неконечным узлом, то есть содержит собственный HTML-код. Вы можете поместить туда многое, но в этом примере у них просто текстовый узел, который точно (или почти точно) состоит из имени класса (Normal для одного и Changed для другого). Вот как функция может получить имя класса CSS, относящееся к этой кнопке; он берет его из текста внутри выбранного элемента <button>.

Я сказал «почти точно» там, потому что на самом деле между текстом кнопки и фактическими классами CSS, которые они определили в правилах CSS (а именно normal и changed), существует разница в регистре букв. Вот почему они должны понизить регистр извлеченного текста кнопки (toLowerCase()) перед присвоением имени класса. Классы CSS чувствительны к регистру (см. раздел Чувствительны ли селекторы CSS к регистру?).

Как я уже сказал, это необычный код. Довольно нецелесообразно создавать сопоставление (особенно неточное сопоставление!) между простым текстом HTML и метаданными кода (в данном случае классами CSS).

person bgoldst    schedule 06.02.2015