Vanilla JavaScript:<Dropdown Select> option.remove(Index) 是如何工作的?

Vanilla JavaScript: How does <Dropdown Select> option.remove(Index) work?

我正在创建一个包含两个菜单的从属下拉菜单。

每当第一个菜单中的选项更改时,第二个菜单的内容也必须更改。

我遵循了两个步骤:

第 1 步:从第二个菜单中删除所有选项

第 2 步:根据在第一个菜单中选择的选项,用选项重新填充第二个菜单。

要删除所有选项,我编写了以下代码:

var select = document.getElementById('1st_select');
var selected = select.value;
var target = document.getElementById('2nd_select');
var targetLength = target.length
console.log("Length"+target.length);
for (var i = 0; i <targetLength; i++) {
    console.log(i);
    target.remove(i);
}

以上代码无效。当第一个菜单中的选项更改时,某些选项仍保留在第二个下拉列表中。

但是如果我只是将遍历循环从

for (var i = 0; i <targetLength; i++)

for (var i = targetLength; i >=0; i--)

它工作正常。

为什么会这样?

请尝试仅在 Pure/Vanilla Javascript 中解释概念。

循环遍历故障的代码片段。

function show_op(id,lb){
    var ops = document.getElementsByClassName('option-contents');
 var op = document.getElementById(id);
 for (var i = 0; i < ops.length; i++) {
  ops[i].style.display='none';
 }
 op.style.display='block';
 var labels = document.getElementsByClassName('option-links');
 var label = document.getElementById(lb);
 for (var i = 0; i < labels.length; i++) {
  labels[i].style.backgroundColor="transparent";
 }
 label.style.backgroundColor="#cccccc";
}

var productsByCategory = {
    A: ["CNC 1", "CNC 2", "CNC 3", "CNC 4"],
    B: ["LASER 1", "LASER 2", "LASER 3", "LASER 4"],
    C: ["RUBBER 1", "RUBBER 2", "RUBBER 3", "RUBBER 4", "RUBBER 5"],
    D: ["PRECISION 1","PRECISION 2","PRECISION 3"]
}
var valuesByCategory = {
    A: ["A1", "A2", "A3", "A4"],
    B: ["B1", "B2", "B3", "B4"],
    C: ["C1", "C2", "C3", "C4", "C5"],
    D: ["D1","D2","D3"]
}
console.log(productsByCategory);
console.log(productsByCategory['A']);
for (var i in productsByCategory['B']){
console.log(productsByCategory['B'][i]);
}
function dropdown(){
 var select = document.getElementById('1st_select');
 var selected = select.value;
 var target = document.getElementById('2nd_select');
 var targetLength = target.length
 console.log("Length"+target.length);
 for (var i = 0; i <targetLength; i++) {
  console.log(i);
  target.remove(i);
 }
 if (selected==0) {
  var option = document.createElement("option");
  option.text="Select Product first";
  option.value="";
  target.add(option);
 }
 if (selected==1) {
  
  for (var i in productsByCategory['A']){
   var option = document.createElement("option");
   option.text=productsByCategory['A'][i];
   option.value=valuesByCategory['A'][i];
   target.add(option);
  }
  
 } 

 else if (selected==2){
  for (var i in productsByCategory['B']){
   var option = document.createElement("option");
   option.text=productsByCategory['B'][i];
   option.value=valuesByCategory['B'][i];
   target.add(option);
  }
 }
 else if (selected==3){
  for (var i in productsByCategory['C']){
   var option = document.createElement("option");
   option.text=productsByCategory['C'][i];
   option.value=valuesByCategory['C'][i];
   target.add(option);
  }
 }
 else {
  for (var i in productsByCategory['D']){
   var option = document.createElement("option");
   option.text=productsByCategory['D'][i];
   option.value=valuesByCategory['D'][i];
   target.add(option);
  }
 }
}
function dropdown2(){
 var select = document.getElementById('2nd_select');
 var selected = select.value; 
 console.log(selected);
}
body{
    height: 100vh;
 margin: 0px;
 overflow-y: auto;
 font-family: 'Roboto';
}
#clear{
  clear: both;
}
.content{
 display: flex;
 background-color: white;
 height: auto;
 margin-top: 0px;
 font-family: 'Roboto';
 z-index: -1;
 min-height: 88%;
}

.links{
 position: relative;
 display: block;
 float: left; 
 width: 30%;
 border-style: solid;
 box-sizing: border-box;
 border-color: black;
 line-height: 3; 
}
.link-contents{
 position: relative;
 display: block;
 float: left;
 left: 0px;
 width: 70%;
 border-style: solid;
 box-sizing: border-box;
 border-color: red;
 
}
.option-links{
 display: block;
 font-size: 30px;
 cursor: pointer;

}
#op1{
 background-color: #cccccc;
}

.footer{
 display: block;
 max-height: 4%;
}


#order_now{
 display: block;
}
<!DOCTYPE html>
<html>
<head>
 <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
 <link rel="stylesheet" type="text/css" href="profile.css">
 <title></title>
</head>
<body>
<div class="content">
  <div class="links">
   <span class="option-links" id="op1" onclick="show_op('order_now','op1');">Order new</span><br/>
  </div>
  <div class="link-contents">
   <div class="option-contents" id="order_now">
    <select id="1st_select" onchange="dropdown();">
     <option value="0">Select</option>
     <option value="1">CNS</option>
     <option value="2">Laser Cut</option>
     <option value="3">Rubber roller</option>
     <option value="4">Fixture</option>
    </select>

    <select id="2nd_select" onchange="dropdown2();">
     <option>Select Product first</option>
    </select>
    
   </div>
  </div>
 
  <div id="clear"></div>

 </div>
  
 <div class="footer">
  A big thank you to all of you.
 </div>
 
 

</body>
<script type="text/javascript" src="profile.js"></script>
</html>

删除此代码段

for (var i = 0; i < targetLength; i++) {
    console.log(i);
    target.remove(i);
  }

with target.innerHTML=''; 这将清空第二个下拉列表并添加新选项

function show_op(id, lb) {
  var ops = document.getElementsByClassName('option-contents');
  var op = document.getElementById(id);
  for (var i = 0; i < ops.length; i++) {
    ops[i].style.display = 'none';
  }
  op.style.display = 'block';
  var labels = document.getElementsByClassName('option-links');
  var label = document.getElementById(lb);
  for (var i = 0; i < labels.length; i++) {
    labels[i].style.backgroundColor = "transparent";
  }
  label.style.backgroundColor = "#cccccc";
}

var productsByCategory = {
  A: ["CNC 1", "CNC 2", "CNC 3", "CNC 4"],
  B: ["LASER 1", "LASER 2", "LASER 3", "LASER 4"],
  C: ["RUBBER 1", "RUBBER 2", "RUBBER 3", "RUBBER 4", "RUBBER 5"],
  D: ["PRECISION 1", "PRECISION 2", "PRECISION 3"]
}
var valuesByCategory = {
  A: ["A1", "A2", "A3", "A4"],
  B: ["B1", "B2", "B3", "B4"],
  C: ["C1", "C2", "C3", "C4", "C5"],
  D: ["D1", "D2", "D3"]
}
console.log(productsByCategory);
console.log(productsByCategory['A']);
for (var i in productsByCategory['B']) {
  console.log(productsByCategory['B'][i]);
}

function dropdown() {
  var select = document.getElementById('1st_select');
  var selected = select.value;
  var target = document.getElementById('2nd_select');
  var targetLength = target.length
  console.log("Length" + target.length);
  target.innerHTML = ''; //changed here
  /*for (var i = 0; i < targetLength; i++) {
    console.log(i);
    target.remove(i);
  }*/
  if (selected == 0) {
    var option = document.createElement("option");
    option.text = "Select Product first";
    option.value = "";
    target.add(option);
  }
  if (selected == 1) {

    for (var i in productsByCategory['A']) {
      var option = document.createElement("option");
      option.text = productsByCategory['A'][i];
      option.value = valuesByCategory['A'][i];
      target.add(option);
    }

  } else if (selected == 2) {
    for (var i in productsByCategory['B']) {
      var option = document.createElement("option");
      option.text = productsByCategory['B'][i];
      option.value = valuesByCategory['B'][i];
      target.add(option);
    }
  } else if (selected == 3) {
    for (var i in productsByCategory['C']) {
      var option = document.createElement("option");
      option.text = productsByCategory['C'][i];
      option.value = valuesByCategory['C'][i];
      target.add(option);
    }
  } else {
    for (var i in productsByCategory['D']) {
      var option = document.createElement("option");
      option.text = productsByCategory['D'][i];
      option.value = valuesByCategory['D'][i];
      target.add(option);
    }
  }
}

function dropdown2() {
  var select = document.getElementById('2nd_select');
  var selected = select.value;
  console.log(selected);
}
body {
  height: 100vh;
  margin: 0px;
  overflow-y: auto;
  font-family: 'Roboto';
}

#clear {
  clear: both;
}

.content {
  display: flex;
  background-color: white;
  height: auto;
  margin-top: 0px;
  font-family: 'Roboto';
  z-index: -1;
  min-height: 88%;
}

.links {
  position: relative;
  display: block;
  float: left;
  width: 30%;
  border-style: solid;
  box-sizing: border-box;
  border-color: black;
  line-height: 3;
}

.link-contents {
  position: relative;
  display: block;
  float: left;
  left: 0px;
  width: 70%;
  border-style: solid;
  box-sizing: border-box;
  border-color: red;
}

.option-links {
  display: block;
  font-size: 30px;
  cursor: pointer;
}

#op1 {
  background-color: #cccccc;
}

.footer {
  display: block;
  max-height: 4%;
}

#order_now {
  display: block;
}
<div class="content">
  <div class="links">
    <span class="option-links" id="op1" onclick="show_op('order_now','op1');">Order new</span><br/>
  </div>
  <div class="link-contents">
    <div class="option-contents" id="order_now">
      <select id="1st_select" onchange="dropdown();">
        <option value="0">Select</option>
        <option value="1">CNS</option>
        <option value="2">Laser Cut</option>
        <option value="3">Rubber roller</option>
        <option value="4">Fixture</option>
      </select>

      <select id="2nd_select" onchange="dropdown2();">
        <option>Select Product first</option>
      </select>

    </div>
  </div>

  <div id="clear"></div>

</div>

<div class="footer">
  A big thank you to all of you.
</div>

这是因为 for (var i = 0; i <targetLength; i++) 目标数组中索引 i 处的选项被替换为 i+1 处的选项(因此后面有 1 个选项)。

例如; 第一次 i=0, en 然后你删除它 target.delete(i) 这将是 target.delete(0) 这将删除索引 0 处的选项,但索引 1 (i 1) 处的选项现在移至 0;然后 JS 将前进到 i 变为 1 的下一个循环,因此跳过它之后的选项。

当您从 i=targetlength 开始时,它会在每个循环中删除最后一个索引,因此不会移动您在目标数组中的选项;

当您从 select 中删除一个元素时,以下所有选项都会重新编制索引。所以如果你在 i = 3 时执行 remove(i),带有 index = 4 的选项变成 index = 35 变成 4,等等。

然后循环递增 i,因此下一次迭代会删除 4。这是最初 5 的选项,所以你最终跳过了原来的 4。结果是您只删除所有其他选项。

target.length-1 循环到 0 没有这个问题,因为你在最后删除了,这对前面元素的索引没有影响。

您还可以使用:

while (target.length > 0) {
    target.remove(0);
}