Rimozione delle opzioni dal tag Select in Vanilla JavaScript con il ciclo "for .. of"


10

Quando si tenta di rimuovere le opzioni dalla selezione, ne rimane sempre una, perché?

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

Questo JS non funziona:

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

E questo non funziona anche:

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

So che ci sono altre soluzioni per raggiungere questo obiettivo, ma vorrei capire perché non funziona come dovrebbe

Risposte:


7

La .optionscollezione è (purtroppo) dal vivo , quindi iterando gli elementi della collezione dal vivo uno a uno e .removeing ognuno si tradurrà in uno strano. (Ad esempio, proprio quando rimuovi il primo oggetto, l' [0]articolo th della collezione diventerà immediatamente l' elemento successivo nella collezione - quello che era prima [1]diventerà [0](e poi una volta che vai al prossimo indice in [1], il nuovo oggetto in posizione 0 non verrà ripetuto)

Utilizzare document.querySelectorAllinvece, che restituisce una raccolta che è statica:

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>

Puoi anche diffonderti in un array (statico) prima di rimuovere elementi ::

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>

Un'altra opzione che ha appena capita al lavoro, perché la collezione è in diretta (ma probabilmente non dovrebbe essere usato, dato che non è intuitivo):

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

Stai rimuovendo elementi da un array, mentre esegui l'iterazione attraverso l'array. Quindi hai:

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

quindi rimuovi l'elemento all'indice 0, che è "uno", lasciandoti con:

["two","three"]

successivamente rimuovi l'elemento all'indice 1, che è "tre", lasciandoti con:

["two"]

non ci sono oggetti all'indice 2, quindi il ciclo si interrompe.

Scorrere invece l'array al contrario :

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>


Il .optionsè non un array, che è la fonte del problema - piuttosto, è un HTMLCollection, che è in diretta. Se fosse un array, sarebbe statico e non ci sarebbero problemi.
CertainPerformance,

1
@CertainPerformance rimozione di elementi da un array come eseguire iterazioni attraverso di essa fa causa il problema che ho illustrato.
symlink il

1
@CertainPerformance Un HTMLOptionsCollectionoggetto agisce in questo contesto come un array.
symlink il

2

Vedo che il tuo obiettivo principale è comprendere il processo che causa ciò, quindi questo dovrebbe illustrare il problema per te:

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) + ".");

Questo ciclo attraversa esattamente lo stesso tipo di processo che il ciclo "for .. of" attraversa per lasciarti con extra nel risultato finale. Il problema è che sta distruggendo i propri indici mentre scorre attraverso di essi, cambiando così il valore a cui si ista realmente riferendo. Quando sto affrontando questo problema, mi piace scorrere indietro l'array in modo da non essere influenzato dalla mia stessa distruzione, in questo modo:

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) + ".");

Spero che questo ti aiuti a capire bene cosa sta succedendo qui. Se hai domande, sentiti libero di lasciarmi un commento.


0

Stai eseguendo il ciclo attraverso lo stesso array in cui l'indice cambia una volta rimosso l'elemento dall'array. Di seguito è riportato l'esempio in cui è possibile scorrere le opzioni senza indice e rimuoverlo dall'array.

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

Ecco il violino

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.