appendChild 不会两次附加相同的元素
appendChild doesn't append the same element twice
我有一个 valuesArray
和一个 transcribedPoems
数组。如果它们都存在一个键,我想在 Transcribed
和 All
子组中向我的 select
元素添加一个 option
。如果没有,那么我希望该选项仅在 All
子组中可用。这是我的代码:
let valuesArray = [
["1", "a manuscript"], ["2", "another one"]
]
const transcribedPoems =['2']
let optGroupTranscribed = document.createElement("optgroup");
optGroupTranscribed.setAttribute("label", "Transcribed")
let optGroupAll = document.createElement("optgroup");
optGroupAll.setAttribute("label", "All")
let select = document.createElement("select");
valuesArray.forEach(function(element) {
let option = document.createElement("option");
option.value = element[0];
option.text = element[1];
if (transcribedPoems.includes(element[0])) {
optGroupTranscribed.appendChild(option);
optGroupAll.appendChild(option);
} else {
optGroupAll.appendChild(option);
}
});
select.appendChild(optGroupTranscribed);
select.appendChild(optGroupAll);
document.getElementById("manifests").appendChild(select);
虽然上面的代码没有向 optGroupTranscribed
添加任何内容。我注意到,如果我从条件中取出 optGroupAll.appendChild(option);
,那么我确实在 transcribed
子组(而不是 All
子组中)有转录的诗歌。不过,我希望转录的诗歌也属于 All
子组。我错过了什么?
我得到的:
<select>
<optgroup label="Transcribed">
<option value="2">another one</option>
</optgroup>
<optgroup label="All">
<option value="1">a manuscript</option>
</optgroup>
</select>
预期结果:
<select>
<optgroup label="Transcribed">
<option value="2">another one</option>
</optgroup>
<optgroup label="All">
<option value="1">a manuscript</option>
<option value="2">another one</option>
</optgroup>
</select>
在 one 循环的 forEach
迭代中,您只创建 one option
元素,依此类推你不能指望结果有两个。
第二次调用 appendChild
实际上 将 移动到 option
那里,将其从第一个选项组中取出。
您可以致电 option.cloneNode(true)
来解决这个问题。
这里有一个有趣的微妙之处。当您使用 createElement
时,它会创建一个 HTMLElement 实例(对于子类 option
)。当您 appendChild
那个元素到另一个元素时,它被放置在那个元素的 DOM 树中。
如果您将同一个元素放置在另一个元素的 DOM 树中,它会使整个树(包含 optGroupTranscribed
和 optGroupAll
) 不是一棵树,因为会有一个 child option
由两个元素共享。
相反,您可以调用 option.cloneNode()
来制作元素的副本。因此,尝试将其更改为:
optGroupTranscribed.appendChild(option.cloneNode());
这样做...
文档:
optionElement = new Option(text, value, defaultSelected, selected)
const
newElm = (tag, props={}) => Object.assign(document.createElement(tag), props)
, transcribedPoems = ['2']
, valuesArray =
[ ['1', 'a manuscript']
, ['2', 'another one' ]
]
, mySelect = document
.querySelector('#manifests')
.appendChild( newElm('select',{name:'select',id:'objectAssign'}))
;
let optGroupTranscribed = mySelect.appendChild(newElm('optgroup',{label:'Transcribed'}))
, optGroupAll = mySelect.appendChild(newElm('optgroup',{label:'All'}))
, doSelect = true
;
valuesArray.forEach(([val,lib]) =>
{
if ( transcribedPoems.includes(val))
{
optGroupTranscribed.appendChild( new Option(lib,val,doSelect,doSelect) )
doSelect = false
}
optGroupAll.appendChild( new Option(lib,val) )
})
<div id="manifests"></div>
我有一个 valuesArray
和一个 transcribedPoems
数组。如果它们都存在一个键,我想在 Transcribed
和 All
子组中向我的 select
元素添加一个 option
。如果没有,那么我希望该选项仅在 All
子组中可用。这是我的代码:
let valuesArray = [
["1", "a manuscript"], ["2", "another one"]
]
const transcribedPoems =['2']
let optGroupTranscribed = document.createElement("optgroup");
optGroupTranscribed.setAttribute("label", "Transcribed")
let optGroupAll = document.createElement("optgroup");
optGroupAll.setAttribute("label", "All")
let select = document.createElement("select");
valuesArray.forEach(function(element) {
let option = document.createElement("option");
option.value = element[0];
option.text = element[1];
if (transcribedPoems.includes(element[0])) {
optGroupTranscribed.appendChild(option);
optGroupAll.appendChild(option);
} else {
optGroupAll.appendChild(option);
}
});
select.appendChild(optGroupTranscribed);
select.appendChild(optGroupAll);
document.getElementById("manifests").appendChild(select);
虽然上面的代码没有向 optGroupTranscribed
添加任何内容。我注意到,如果我从条件中取出 optGroupAll.appendChild(option);
,那么我确实在 transcribed
子组(而不是 All
子组中)有转录的诗歌。不过,我希望转录的诗歌也属于 All
子组。我错过了什么?
我得到的:
<select>
<optgroup label="Transcribed">
<option value="2">another one</option>
</optgroup>
<optgroup label="All">
<option value="1">a manuscript</option>
</optgroup>
</select>
预期结果:
<select>
<optgroup label="Transcribed">
<option value="2">another one</option>
</optgroup>
<optgroup label="All">
<option value="1">a manuscript</option>
<option value="2">another one</option>
</optgroup>
</select>
在 one 循环的 forEach
迭代中,您只创建 one option
元素,依此类推你不能指望结果有两个。
第二次调用 appendChild
实际上 将 移动到 option
那里,将其从第一个选项组中取出。
您可以致电 option.cloneNode(true)
来解决这个问题。
这里有一个有趣的微妙之处。当您使用 createElement
时,它会创建一个 HTMLElement 实例(对于子类 option
)。当您 appendChild
那个元素到另一个元素时,它被放置在那个元素的 DOM 树中。
如果您将同一个元素放置在另一个元素的 DOM 树中,它会使整个树(包含 optGroupTranscribed
和 optGroupAll
) 不是一棵树,因为会有一个 child option
由两个元素共享。
相反,您可以调用 option.cloneNode()
来制作元素的副本。因此,尝试将其更改为:
optGroupTranscribed.appendChild(option.cloneNode());
这样做...
文档:
optionElement = new Option(text, value, defaultSelected, selected)
const
newElm = (tag, props={}) => Object.assign(document.createElement(tag), props)
, transcribedPoems = ['2']
, valuesArray =
[ ['1', 'a manuscript']
, ['2', 'another one' ]
]
, mySelect = document
.querySelector('#manifests')
.appendChild( newElm('select',{name:'select',id:'objectAssign'}))
;
let optGroupTranscribed = mySelect.appendChild(newElm('optgroup',{label:'Transcribed'}))
, optGroupAll = mySelect.appendChild(newElm('optgroup',{label:'All'}))
, doSelect = true
;
valuesArray.forEach(([val,lib]) =>
{
if ( transcribedPoems.includes(val))
{
optGroupTranscribed.appendChild( new Option(lib,val,doSelect,doSelect) )
doSelect = false
}
optGroupAll.appendChild( new Option(lib,val) )
})
<div id="manifests"></div>