我试图通过JavaScript点击元素中的所有隐藏类.这是我用来尝试这样做的虚拟代码:
<style>
.hidden {display:none;}
</style>
<div>Value 1</div>
<div class="hidden">Value 2</div>
<div class="hidden">Value 3</div>
<div class="hidden">Value 4</div>
<button onclick="removeHidden()">Show All</button>
<script>
function removeHidden()
{
var hidden = document.getElementsByClassName("hidden");
for(var i=0; i<hidden.length; i++)
{
hidden[i].classList.remove("hidden");
}
}
</script>Run Code Online (Sandbox Code Playgroud)
单击按钮时,我希望删除所有类"隐藏",但奇怪的是,它会从第二个div和第四个div中删除隐藏的类,但会跳过第三个.
我得到的结果是:
Value 1
Value 2
Value 4
Run Code Online (Sandbox Code Playgroud)
知道为什么那是因为我真的不明白吗?
我也尝试过这段代码但结果相同:
var els = document.getElementsByClassName("hidden");
Array.prototype.forEach.call(els, function(el) {
el.ClassList.remove("hidden");
});
Run Code Online (Sandbox Code Playgroud)
问题是getElementsByClassName()返回"实时"节点列表,该列表是在您引用列表时随时更新的列表.这可确保您始终获得最新的元素引用.这是一种昂贵的结构,实际上仅适用于需要时的罕见用例.
每次代码引用hidden变量时,都会重新扫描DOM以查找具有hidden该类的元素,并在开始删除该类之后,列表的长度缩小一.这是因为这一变化length导致一个项目被跳过.
要getElementsByClassName()在此处正确使用,请先从最后一个元素中删除该类,然后向后移动到第一个元素.这可确保随着节点列表的长度缩小,您不会跳过任何节点.
<style>
.hidden {display:none;}
</style>
<div>Value 1</div>
<div class="hidden">Value 2</div>
<div class="hidden">Value 3</div>
<div class="hidden">Value 4</div>
<button onclick="removeHidden()">Show All</button>
<script>
function removeHidden()
{
var hidden = document.getElementsByClassName("hidden");
for(var i = hidden.length-1; i > -1; i--)
{
hidden[i].classList.remove("hidden");
}
}
</script>Run Code Online (Sandbox Code Playgroud)
但是,因为实时节点列表会导致性能损失,所以一般情况下不要使用它们.相反,使用静态节点列表,您可以使用更现代,更灵活的方式获得静态节点列表.querySelectorAll().此外,如果我们将返回的静态节点列表.querySelectorAll()转换为Array,我们可以使用Array API对其进行迭代.forEach(),从而无需索引器.
<style>
.hidden {display:none;}
</style>
<div>Value 1</div>
<div class="hidden">Value 2</div>
<div class="hidden">Value 3</div>
<div class="hidden">Value 4</div>
<button onclick="removeHidden()">Show All</button>
<script>
function removeHidden()
{
// Get all the elements that match the selector into an Array
var hidden = Array.prototype.slice.call(document.querySelectorAll(".hidden"));
// Now we can loop using the Array API
hidden.forEach(function(item){
item.classList.remove("hidden");
});
}
</script>Run Code Online (Sandbox Code Playgroud)