Видалення параметрів з тегу Select у ванільному JavaScript з циклом "for .. of"


10

Коли ви намагаєтесь видалити параметри з вибору, завжди залишається один, чому?

<select id="form-select">   
<option>111</option>
<option>222</option>
<option>333</option>
</select>

Цей JS не працює:

var t = document.querySelector('#form-select'); 
for(var i of t.options) {
      t.remove(i.index)
    }

І це також не працює:

for(var i of document.querySelector('#form-select').options) {
  i.remove()
}

Я знаю, що для цього є й інші рішення, але я хотів би зрозуміти, чому це не працює так, як належить

Відповіді:


7

.optionsКолекція (на жаль) в прямому ефірі , так що ітерація елементи живої колекції в один-на-один і .removeІНГ кожен призведе до кожної непарної тримається. (Наприклад, коли ви видалите перший елемент, цей [0]елемент колекції одразу стане наступним елементом у колекції - тим, що раніше було [1], стане [0](а потім, коли ви перейдете до наступного індексу на [1], новий елемент у позиції) 0 не буде повторено)

Використовуйте document.querySelectorAllнатомість, що повертає статичну колекцію:

for (const option of document.querySelectorAll('#form-select > option')) {
  option.remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>

Ви також можете поширити в (статичний) масив перед видаленням елементів ::

for (const option of [...document.querySelector('#form-select').options]) {
  option.remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>

Інший варіант , який як раз трапляється до роботи , тому що колекція живий (але , ймовірно , не слід використовувати, так як це не інтуїтивно):

const { options } = document.querySelector('#form-select');
while (options.length) {
  options[0].remove();
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>


3

Ви видаляєте елементи з масиву під час ітерації через масив. Отже, у вас є:

["one","two","three"]

тоді ви видаляєте елемент з індексу 0, який є "один", залишаючи вас із:

["two","three"]

далі ви видаляєте елемент з індексу 1, який є "трьома", залишаючи вас із:

["two"]

в індексі 2 немає елемента, тому цикл зупиняється.

Ітерація замість масиву відбувається навпаки :

const t = document.querySelector("#form-select")

for (let i = t.options.length-1; i >= 0; i--) {
  t.removeChild(t.options[i])
}
<select id="form-select">
  <option>111</option>
  <option>222</option>
  <option>333</option>
</select>


.optionsЦе НЕ масив, який є джерелом проблеми - швидше, що це HTMLCollection, який знаходиться під напругою. Якби це масив, він був би статичним, і проблем не було б.
Окреме виконання

1
@CertainPerformance видалення елементів з масиву, коли ви повторюєте його , викликає проблему, яку я проілюстрував.
symlink

1
@CertainPerformance HTMLOptionsCollectionОб'єкт діє в цьому контексті як масив.
symlink

2

Я бачу, що ваша основна мета - зрозуміти процес, який спричиняє це, тому це має ілюструвати проблему для вас:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = 0; i < arr.length; i++){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i + 1) + " and continue the loop.");
}
console.log("i is too high to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

Цей цикл проходить через той самий тип процесу, який проходить цикл "за ..", щоб залишити вас з додатковими можливостями в кінцевому результаті. Проблема полягає в тому, що вона руйнує власні індекси під час повторення через них, тим самим змінюючи значення, на яке iдійсно йдеться. Коли я стикаюся з цією проблемою, мені подобається перебирати масив назад, так що я не зачіпаю моє власне знищення, як-от так:

var arr = ["one", "two", "three", "four", "five", "six"];

for(var i = arr.length - 1; i >= 0; i--){
	console.log("i is " + i + ", so we are removing \"" + arr[i] + "\" from " + JSON.stringify(arr) + ".");
	arr.splice(i, 1);
	console.log("After that removal, the array is " + JSON.stringify(arr) + ". We'll now iterate i to " + (i - 1) + " and continue the loop.");
}
console.log("i is too low to grab a value from the array, so we're finished. We're left with " + JSON.stringify(arr) + ".");

Я сподіваюся, що це допоможе вам зрозуміти, що відбувається тут ретельно. Якщо у вас є якісь питання, не соромтесь залишити мені коментар.


0

Ви перебираєтеся через той самий масив, де змінюється індекс, коли ви виймаєте елемент з масиву. Нижче наведено зразок, де ви можете переглядати параметри без індексу та видаляти його з масиву.

var selectOptions = document.querySelectorAll('#remove-option>option');
selectOptions.forEach(function(selectOption) {
  selectOption.remove();
  selectOption = null;
});

Ось скрипка

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.