querySelectorAll 不起作用

问题描述 投票:0回答:3

我有一个要求,我必须拾取容器内的最后一个

.div
并对其应用一些业务逻辑。最后一个
.div
的选择必须是动态的,因为用户可以选择添加/删除
.div
元素。

最初我尝试使用

querySelectorAll
,但似乎不起作用。所以我决定将其更改为
getElementsByClassName
,令人惊讶的是它以相同的逻辑工作。有人可以帮我解释为什么
remove_div
不起作用而第二个 (
remove_div_2
) 起作用吗?

注意:我并不是在寻找问题的修复/解决方案,因为我已经继续使用第二个选项。我只是想知道为什么带有

querySelectorAll
的选项不起作用。

下面是我的代码:

HTML:

<div id='container'>
    <div id='div1' class='div'>This is Div 1</div>
    <div id='div2' class='div'>This is Div 2</div>
    <div id='div3' class='div'>This is Div 3</div>
</div>
<button type='button' id='append_div'>Append Div</button>
<button type='button' id='remove_div'>Remove Div</button>
<button type='button' id='remove_div_2'>Remove Div 2</button>

JavaScript:

window.onload = function () {
    var elementToStyle = document.querySelectorAll("#container .div");
    elementToStyle[elementToStyle.length - 1].classList.add('red');

    document.getElementById('append_div').onclick = function () {
       var divToInsert = document.createElement('div');
       divToInsert.id = 'new_div';
       divToInsert.className = 'div';
       divToInsert.innerHTML = 'This is an appended div';
       document.getElementById('container').appendChild(divToInsert);
       var elToStyle = document.querySelectorAll("#container .div");
       for (i = 0; i < elToStyle.length; i++)
           elToStyle[i].classList.remove('red');
           elToStyle[elToStyle.length - 1].classList.add('red');
       };

       document.getElementById('remove_div').onclick = function () {
           var elToStyle = document.querySelectorAll("#container .div");
           document.getElementById('container').removeChild(elToStyle[elToStyle.length - 1]);
           elToStyle[elToStyle.length - 1].classList.add('red');
       };

       document.getElementById('remove_div_2').onclick = function () {
           var elToStyle = document.getElementsByClassName('div');
           document.getElementById('container').removeChild(elToStyle[elToStyle.length - 1]);
           elToStyle[elToStyle.length - 1].classList.add('red');
       };
   }
javascript html selectors-api
3个回答
15
投票

原因是因为

querySelectorAll
方法返回一个静态列表。使用
querySelectorAll
之后对文档所做的任何更改(如本例中的
removeChild
)都不会反映在返回的节点列表中。因此
elToStyle[elToStyle.length - 1]
仍会指向被删除的节点。

另一方面,

getElementsByClassName
返回节点的实时列表。这意味着
elToStyle[elToStyle.length - 1]
始终指向最后一个
.div
,无论节点列表准备好与否后对文档进行了任何更改。

以下是官方文档的摘录这里

querySelectorAll()方法返回的NodeList对象必须是 静态的,非实时的([DOM-LEVEL-3-CORE],第 1.1.1 节)。随后的 不得更改基础文档的结构 反映在 NodeList 对象中。这意味着该对象将 相反,包含位于 创建列表时的文档。

注意: 您可以通过在

console.log(elToStyle);
之前和之后执行
removeChild
来看到这一点。


0
投票

如果您想引用最后一个除法元素,只需执行以下操作...

var id = 'container';
var d = document.getElementById(id).getElementsByTagName('div')
var lastDiv = d[d.length - 1];

..然后应用您的

querySelector


0
投票

您可以使用 querySelectorAll() 访问所有元素,如下所示:

document.querySelectorAll('?').forEach(function(element) {
   // Now you can apply your changes to each element 
});
© www.soinside.com 2019 - 2024. All rights reserved.