html 为什么选项元素不附加在两个选择标签内,而只附加在最后一个选择标签上?

pieyvz9o  于 2023-03-16  发布在  其他
关注(0)|答案(3)|浏览(113)

网址:

<div class="from">
    <select
        name=""
        class="droplistOptions"
    >
        <!--insert option element here-->
    </select>
</div>
<p class="to-seprator">To</p>
<div class="to">
    <select
        name=""
        class="droplistOptions"
    >
        <!--insert option element here also -->
    </select>
</div>

验证码:

const droplists = document.querySelectorAll('.droplistOptions');
countryNames = ['usa', 'India', 'china', 'japan'];
countryNames.forEach((country) => {
    const optionElement = document.createElement('option');
    optionElement.value = country;
    optionElement.textContent = country;
    droplists.forEach((item) => item.append(optionElement));
});

在上面的代码中,我想插入countryNames数组中的所有国家名称作为html中的两个选择标记内的选项元素,但当我使用append时,它只在html中的最后一个或第二个选择标记中添加选项元素,并且第一个选择标记为空,在第一个选择标记内没有插入选项元素。我不知道我犯了什么错误。我想了解为什么会这样。如果是这样工作的,它应该在select标记的两个位置都附加optionElement,因为drolists是nodelist数组,而forEach迭代每个元素,所以

unguejic

unguejic1#

您创建并附加到第一个列表的optionsElement,随后将附加(移动)到第二个列表。Deep clone在附加元素之前对其执行以下操作:

const droplists = document.querySelectorAll(".droplistOptions");
const countryNames = ['usa', 'India', 'china', 'japan']
countryNames.forEach((country) => {
  const optionElement = document.createElement("option");
  optionElement.value = country;
  optionElement.textContent = country;
  droplists.forEach((item) => item.append(optionElement.cloneNode(true)));
});
<div class="from">
  <select name="" class="droplistOptions">
    <!--insert option element here-->
  </select>
</div>
<p class="to-seprator">To</p>
<div class="to">
  <select name="" class="droplistOptions">
    <!--insert option element here also -->
  </select>
</div>

或者为每个列表创建一个新元素:
一个二个一个一个
如果列表很长,最好创建一个片段,将所有optionElement节点附加到该片段,然后将该片段的克隆附加到列表中,这样可以避免对DOM进行多次连续更改:

const droplists = document.querySelectorAll(".droplistOptions");
const countryNames = ['usa', 'India', 'china', 'japan']

const fragment = new DocumentFragment();
countryNames.forEach((country) => {
  const optionElement = document.createElement("option");
  optionElement.value = country;
  optionElement.textContent = country;
  
  fragment.append(optionElement);
});

droplists.forEach((item) => {
  item.append(fragment.cloneNode(true));
});
<div class="from">
  <select name="" class="droplistOptions">
    <!--insert option element here-->
  </select>
</div>
<p class="to-seprator">To</p>
<div class="to">
  <select name="" class="droplistOptions">
    <!--insert option element here also -->
  </select>
</div>
v7pvogib

v7pvogib2#

你不能在DOM的不同地方插入相同的标签。它是相同的元素,当你调用“append”时,它会把你的选项带到第一个<select>,然后替换到第二个,插入不像克隆那样工作。
您需要为每个列表创建新的<option>

const droplists = document.querySelectorAll(".droplistOptions");
countryNames = ['usa','India','china','japan']
countryNames.forEach((country) => {
 droplists.forEach((item) => {
    const optionElement = document.createElement("option");
    optionElement.value = country;
    optionElement.textContent = country;
    item.append(optionElement));
 });
});
eaf3rand

eaf3rand3#

因为在.forEach循环中只创建了一个option元素--每次调用.appends时,都要将该元素从第一个select元素移动到第二个元素。
有很多方法可以实现这一点,但我喜欢使用innerHTML,尽管这样会在编辑器中丢失语法语义。这样做性能会高得多,因为可以避免对象操作,垃圾收集器也不需要管理不必要的DOM元素对象。
此外,考虑在代码中使用更合适的for...of循环,而不是.forEach构造。.forEach实际上只存在于非赋值数组上。同样,这也会带来性能优势,因为您不需要在.forEach方法创建的内存中存储函数对象和闭包。

const droplists = document.querySelectorAll('.droplistOptions');
const countryNames = ['usa', 'India', 'china', 'japan'];

for (const country of countryNames) {
  for (const list of droplists) {
    item.innerHTML = `${list.innerHTML}<option value="${country}">${country}</option>`;
  }
}
<div class="from">
  <select name="" class="droplistOptions">
    <!--insert option element here-->
  </select>
</div>
<p class="to-seprator">To</p>
<div class="to">
  <select name="" class="droplistOptions">
    <!--insert option element here also -->
  </select>
</div>

相关问题