JavaScript中getElementsByClassName集合数量自动减少问题求助
问题描述
我有一个主div,内部包含3个子div,希望在body的onload函数中获取这3个class为grid-section的子div,通过修改class属性改变它们的显示状态。对应的HTML和JavaScript代码如下:
HTML代码
<div class="w-100 vh-100" id="main-grid"> <div class="border border-dark grid-section"></div> <div class="border border-dark grid-section"> <div class="py-5 border border-danger d-flex justify-content-center align-items-center h-100"> <div> <h2 class="text-primary" id="select-action">Select Form Action</h2> <div class="list-group"> <button type="button" class="list-group-item list-group-item-action" aria-current="true" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span> Sum of Natural Numbers</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Factorial Calculation</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Multiplication Table</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Count Digits in a Number</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Reverse a Number</button> <button type="button" class="list-group-item list-group-item-action" aria-current="true" onclick="ChangeView(this)"> <span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Sum of Digits</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Print Even Numbers</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Print Odd Numbers</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Sum of Even Numbers</button> <button type="button" class="list-group-item list-group-item-action" onclick="ChangeView(this)"><span class="me-2"><i class="fa-solid fa-circle-chevron-right" style="color: #74C0FC;"></i></span>Sum of Odd Numbers</button> </div> </div> </div> </div> <div class="border border-dark grid-section"></div> </div>
JavaScript代码
function setInitialView() { if (mainGrid) { var columns = mainGrid.getElementsByClassName("grid-section"); if (columns != null && columns.length == 3) { try { columns[0].setAttribute("class", "d-none"); columns[1].setAttribute("class", "d-block"); columns[2].setAttribute("class", "d-none"); } catch (e) { } let check = false; } } }
遇到的问题
初始获取到的columns集合长度为3,但执行columns[0].setAttribute('class', 'd-none')后,columns.length变为2;执行columns[1].setAttribute('class', 'd-block')后变为1,访问columns[2]时返回null并抛出异常,不清楚为何集合会自动更新。
原因分析
你用getElementsByClassName()获取到的是动态HTMLCollection集合,它会实时同步DOM的变化。当你用setAttribute替换元素的class时,元素失去了grid-section这个类,就不再符合集合的筛选条件,会被自动移除,导致集合长度不断缩短:
- 修改第一个元素的class为
d-none,它失去grid-section类,集合只剩2个元素; - 此时原来的第二个元素变成了
columns[0],修改它的class后,它也失去grid-section类,集合长度变为1; - 原来的第三个元素现在是
columns[0],但你仍用columns[2]访问,自然会得到null并报错。
解决方案
有两种常用的解决方式:
方法1:将动态集合转为静态数组
把HTMLCollection转为普通数组,这样后续DOM变化不会影响数组内容:
function setInitialView() { if (mainGrid) { // 转为静态数组 var columns = Array.from(mainGrid.getElementsByClassName("grid-section")); if (columns.length == 3) { columns[0].setAttribute("class", "d-none"); columns[1].setAttribute("class", "d-block"); columns[2].setAttribute("class", "d-none"); } } }
也可以用扩展运算符[...mainGrid.getElementsByClassName("grid-section")]来转换数组。
方法2:用classList添加/移除类(推荐)
不要直接替换整个class属性,而是用classList操作类,这样元素不会丢失grid-section类,集合也不会变化:
function setInitialView() { if (mainGrid) { var columns = mainGrid.getElementsByClassName("grid-section"); if (columns.length == 3) { // 给第一个元素添加隐藏类,移除原有不需要的类 columns[0].classList.add('d-none'); columns[0].classList.remove('border', 'border-dark', 'grid-section'); // 给第二个元素添加显示类,移除原有不需要的类 columns[1].classList.add('d-block'); columns[1].classList.remove('border', 'border-dark', 'grid-section'); // 给第三个元素添加隐藏类,移除原有不需要的类 columns[2].classList.add('d-none'); columns[2].classList.remove('border', 'border-dark', 'grid-section'); } } }
这种方式更灵活,也符合类操作的最佳实践,不会意外丢失元素上的其他类。
内容的提问来源于stack exchange,提问作者Maryam
相关产品推荐
相关产品推荐

