Почему итерация по [i] в ​​DOM querySelector для цикла позволяет мне использовать прослушиватель событий в любом порядке? - PullRequest
0 голосов
/ 08 июля 2019

В следующем коде я создал цикл for, который позволяет мне создавать оповещения для любой из 5 кнопок, расположенных на простой веб-странице. Мой вопрос: почему это форматирование позволяет мне нажимать любую кнопку, чтобы вызвать предупреждение, если [i] в ​​моем селекторе запросов повторяется на 1? Разве мне нельзя позволять нажимать кнопки только в порядке их индекса от 0 до 5? Что происходит под капотом, который заставляет [0] в цикле for работать для любой кнопки, независимо от порядка, даже когда я технически нажимаю на элемент [5]?

for (var i = 0; 
i<document.querySelectorAll(".drum").length; i++){
document.querySelectorAll(".drum") 
[i].addEventListener("click", function () {
alert("I got clicked!");
});
}

Ответы [ 2 ]

0 голосов
/ 08 июля 2019

Доказательство того, что у вас есть несколько (здесь, 5) различных обработчиков событий (отражающих как вопрос, так и комментарий, который у вас есть в другом ответе):

for (let i = 0; i<document.querySelectorAll(".drum").length; i++){
  document.querySelectorAll(".drum")[i].addEventListener("click", function () {
    alert("I, "+i+", got clicked!");
  });
}
<button class="drum">a</button>
<button class="drum">s</button>
<button class="drum">d</button>
<button class="drum">f</button>
<button class="drum">g</button>

(Используется let, который «локализует» i в {} цикла, практически имея 5 различных i переменных - если вы попробуете с var, это создаст один, верхний уровень i, и все обработчики событий будут отображать 5, значение i при выходе из цикла).

Если вы хотите, чтобы одновременно работал один прослушиватель событий, вы можете расширить предыдущую попытку с помощью переменной expected:

var expected = 0;
for (let i = 0; i<document.querySelectorAll(".drum").length; i++){
  document.querySelectorAll(".drum")[i].addEventListener("click", function () {
    if(i === expected){
      alert("I, "+i+", got clicked!");
      expected = (i+1) % document.querySelectorAll(".drum").length;
    }
  });
}
<button class="drum">a</button>
<button class="drum">s</button>
<button class="drum">d</button>
<button class="drum">f</button>
<button class="drum">g</button>

В этом коде все обработчики событий все еще существуют, просто они игнорируют случайные щелчки.

А затем вы можете ввести sequence, за которым пользователь должен следовать:

let sequence = [0,2,2,1,3,4,0];
let expected = 0; // just this is an index in sequence now
for (let i = 0; i<document.querySelectorAll(".drum").length; i++){
  document.querySelectorAll(".drum")[i].addEventListener("click", function () {
    if(i === sequence[expected]){
      alert("I, "+i+", got clicked!");
      expected = (expected+1) % sequence.length;
    }
  });
}
<button class="drum">a</button>
<button class="drum">s</button>
<button class="drum">d</button>
<button class="drum">f</button>
<button class="drum">g</button>
<br>||: a,d,d,s,f,g,a :||

Конечно, document.querySelectorAll() это не то, что вы хотите вызывать 2 раза для каждой итерации цикла, и еще раз, когда цикл заканчивается, так что вы могли бы вместо этого сохранить его результат в переменной. Кроме того, здесь нет реальной необходимости иметь несколько функций-обработчиков событий:

let sequence = ['a','d','d','s','f','g','a'];
let expected = 0;

function clicky(event){
  let buttontext=event.target.innerText;
  if(buttontext===sequence[expected]){
    alert("I, "+buttontext+", got clicked!");
    expected = (expected+1) % sequence.length;
  }
}

let drums=document.querySelectorAll(".drum");
for (let i = 0; i<drums.length; i++){
  drums[i].addEventListener("click", clicky);
}
<button class="drum">a</button>
<button class="drum">s</button>
<button class="drum">d</button>
<button class="drum">f</button>
<button class="drum">g</button>
<br>||: a,d,d,s,f,g,a :||

Жаль, что это больше отвечает на то, что вы, вероятно, делаете, чем на самом деле.

0 голосов
/ 08 июля 2019

Ваш цикл for эквивалентен:

// Define an action to do when user clicks, but pass to the next line without waiting that the click event to occur
document.querySelectorAll(".drum")[0].addEventListener(...);
document.querySelectorAll(".drum")[1].addEventListener(...);
document.querySelectorAll(".drum")[2].addEventListener(...);
...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...