Вставка элементов в массив с помощью EventListener
Я пытаюсь обновить массив значениями, как только пользователь нажимает на элемент в DOM. Кажется, что элементы помещаются в массив внутри анонимной функции, но вне функции массив все еще пуст. Как я могу это исправить? Вот код JavaScript:
function getSelection() {
var selections = [];
var container = document.getElementById("main-container");
var choices = document.querySelectorAll('li');
choicesLength = choices.length;
for(var i = 0; i < choicesLength; i++) {
choices[i].addEventListener("click", function(){
var position = this.getAttribute("value");
selections.push(position);
// logs array and updates with each click
console.log(selections);
});
}
// logs empty array
console.log(selections);
}
В основном, после того, как элементы нажаты, основной массив должен быть обновлен в соответствии с тем, что они щелкнули.
Любая помощь будет оценена.
Спасибо
4 ответа
Функция, которую вы передаете addEventListener
не будет работать, пока не произойдет событие.
Вы не можете нажать ни один из пунктов списка до console.log
который запускается сразу после того, как назначение срабатывает.
В основном, после того, как элементы нажаты, основной массив должен быть обновлен в соответствии с тем, что они щелкнули.
... и вот что будет. Посмотрите на результаты console.log
внутри обработчика кликов.
Это о Javascript Scoping, вы можете больше об этом здесь:
Узнайте больше о Javascript Scoping и подъем
Первый console.log(selection) является локальным, в то время как последний console.log(selection) является глобальным, они не совпадают, поэтому он пуст. Вот отредактированная форма моего решения:
function getSelection() {
var selections = [];
var container = document.getElementById("main-container");
var choices = document.querySelectorAll('li');
choicesLength = choices.length;
for (var i = 0; i < choicesLength; i++) {
choices[i].addEventListener("click",pushArray(i));
}
function pushArray(elm) {
var position = choices[elm].getAttribute("value");
selections.push(position);
// logs array and updates with each click
console.log(selections);
}
// logs empty array
console.log(selections);
}
document.body.addEventListener("load", getSelection());
<ul>
<li value="1">1</li>
<li value="2">2</li>
<li value="3">3</li>
<li value="4">4</li>
<li value="5">5</li>
<li value="6">6</li>
<li value="7">7</li>
<li value="8">8</li>
<li value="9">9</li>
<li value="10">10</li>
</ul>
В основном двигаться selections
отус функции getSelection
и сделать это публичным.
var selections = [];
function getSelection() {
var container = document.getElementById("main-container");
var choices = document.querySelectorAll('li');
choicesLength = choices.length;
for(var i = 0; i < choicesLength; i++) {
choices[i].addEventListener("click", function(){
var position = this.getAttribute("value");
selections.push(position);
console.log(selections);
});
}
console.log(selections);
}
window.onload = getSelection;
// access selections outside of getSelection()
setInterval(function () {
if (selections.length < 2) {
console.log('length is smaller than two.');
}
}, 1500);
<ul><li value="1">1</li><li value="2">2</li><li value="3">3</li><li value="4">4</li><li value="5">5</li><li value="6">6</li></ul>
В дополнение к моему комментарию, я думаю, что замыкания могут решить эту проблему довольно эффективно.
Я не проверял следующий код:
function getSelection() {
this.selections = [];
var container = document.getElementById("main-container");
var choices = document.querySelectorAll('li');
choicesLength = choices.length;
var that = this;
for(var i = 0; i < choicesLength; i++) {
choices[i].addEventListener("click", function(){
var position = this.getAttribute("value");
that.selections.push(position); //Explicitly specify context
// logs array and updates with each click
console.log(that.selections);
});
}
return function(){
this.selections;
}
}
Вы называете getSelection
функционировать так:
var getUpdatedArray = getSelection();
//At a later stage when you want the array just do:
getUpdatedArray(); //This should return the selections array.
Я явно связываю selections
массив для вашей функции, выполнив this.selections = []
а затем установить этот контекст внутри слушателей щелчка, выполнив var that = this
,
Чтобы повторить проблему:
Вы были обязательными слушателями событий в вашем getSelection
метод, который вызывается только один раз. Однако щелчки могут произойти в любое время позже. Так что вам нужно обеспечить две вещи:
selections
массив, указанный вclick
Обработчик события - это тот, который определен в областиgetSelection
метод.- Каким-то образом, сохранить рамки
getSelection
метод даже после того, как он выполнен.
Замыкания, волшебным образом решают обе эти проблемы.:)
Хорошая отправная точка для того, почему использовать закрытие - это.