Xóa các tùy chọn khỏi thẻ Chọn trong Vanilla JavaScript bằng vòng lặp cho ..


10

Khi cố gắng loại bỏ các tùy chọn khỏi lựa chọn, luôn luôn có một tùy chọn, tại sao?

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

JS này không hoạt động:

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

Và điều này cũng không hoạt động:

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

Tôi biết rằng có những giải pháp khác để đạt được điều đó, nhưng tôi muốn hiểu tại sao nó không hoạt động như mong muốn

Câu trả lời:


7

Bộ .optionssưu tập là (không may) trực tiếp , do đó, việc lặp đi lặp lại từng mục một của bộ sưu tập trực tiếp và .removemỗi lần một kết quả sẽ dẫn đến mọi thứ lẻ được giữ lại. (Ví dụ, ngay khi bạn xóa mục đầu tiên, mục [0]thứ nhất của bộ sưu tập sẽ ngay lập tức trở thành mục tiếp theo trong bộ sưu tập - mục đích [1]sẽ trở thành [0](và sau đó khi bạn chuyển đến chỉ mục tiếp theo tại [1], mục mới sẽ ở vị trí 0 sẽ không bị lặp lại)

Sử dụng document.querySelectorAllthay thế, trả về một bộ sưu tập tĩnh:

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>

Bạn cũng có thể trải thành một mảng (tĩnh) trước khi loại bỏ các phần tử ::

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>

Một tùy chọn khác chỉ xảy ra để hoạt động vì bộ sưu tập đang hoạt động (nhưng có lẽ không nên sử dụng, vì nó không trực quan):

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

Bạn đang xóa các mục khỏi một mảng, khi bạn lặp qua các mảng. Vì vậy, bạn có:

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

sau đó bạn xóa mục tại chỉ mục 0, đó là "một", để lại cho bạn:

["two","three"]

Tiếp theo, bạn xóa mục này tại chỉ mục 1, đó là "ba", để lại cho bạn:

["two"]

không có mục nào ở chỉ số 2, vì vậy vòng lặp dừng lại.

Thay vào đó, lặp lại qua mảng ngược lại :

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>


Các .optionskhông một mảng, mà là nguồn gốc của vấn đề - đúng hơn, nó là một HTMLCollection, đó là sống. Nó là một mảng, nó là tĩnh và sẽ không có vấn đề gì.
SurePerformance

1
@CertainPerformance loại bỏ các phần tử khỏi một mảng khi bạn lặp qua nó sẽ gây ra vấn đề tôi đã minh họa.
symlink

1
@CertainPerformance Một HTMLOptionsCollectionđối tượng hoạt động trong bối cảnh này giống như một mảng.
symlink

2

Tôi thấy rằng mục tiêu chính của bạn là hiểu quá trình gây ra điều này xảy ra, vì vậy điều này sẽ minh họa vấn đề cho bạn:

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

Vòng lặp này trải qua cùng một loại quy trình mà vòng lặp "for .. of" của bạn đi qua để lại cho bạn các tính năng bổ sung trong kết quả cuối cùng. Vấn đề là nó đang phá hủy các chỉ số của chính nó khi nó lặp qua chúng, do đó thay đổi giá trị ithực sự được đề cập. Khi tôi đang phải đối mặt với vấn đề này, tôi như để lặp qua mảng ngược vì vậy tôi không bị ảnh hưởng bởi sự tàn phá của riêng tôi, như vậy:

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

Tôi hy vọng điều này sẽ giúp bạn hiểu những gì đang diễn ra ở đây một cách triệt để. Nếu bạn có bất kỳ câu hỏi, hãy để lại cho tôi một bình luận.


0

Bạn đang lặp qua cùng một mảng nơi chỉ số thay đổi khi bạn xóa mục khỏi mảng. Dưới đây là mẫu mà bạn có thể lặp qua các tùy chọn mà không cần chỉ mục và xóa nó khỏi mảng.

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

Đây là câu đố

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.