querySelectorAll 不起作用

Posted

技术标签:

【中文标题】querySelectorAll 不起作用【英文标题】:querySelectorAll not working 【发布时间】:2013-09-15 02:57:47 【问题描述】:

我有一个要求,我必须在容器中提取最后一个 .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');
       ;
   

【问题讨论】:

【参考方案1】:

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

而另一方面,getElementsByClassName 返回一个活动的节点列表。这意味着elToStyle[elToStyle.length - 1] 将始终指向最后一个.div,无论在准备好节点列表后是否对文档进行了任何更改。

以下是来自here的官方文档的摘录

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

注意:您可以通过在 removeChild 之前和之后执行 console.log(elToStyle); 来看到这一点。

【讨论】:

【参考方案2】:

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

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

..然后申请您的querySelector

【讨论】:

我认为用户想要class='div' 的最后一个元素,因为它在问题中被称为.div

以上是关于querySelectorAll 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Puppeteer:使用page.querySelectorAll()不是一个函数

getElementsByTagName 似乎不起作用

Python BigQuery客户端缓存不起作用

JS中querySelectorAll的作用

Array.prototype.slice.call() & wrapper.querySelectorAll() 有啥作用?

滚动捕捉和滚动整页