querySelectorAll不起作用 [英] querySelectorAll not working

查看:312
本文介绍了querySelectorAll不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要求,即必须在容器中拾取最后一个 .div 并将一些业务逻辑应用于该容器。选择最后一个 .div 必须是动态的,因为用户可以选择添加/删除 .div 元素。

最初我尝试过使用 querySelectorAll ,但它似乎没有奏效。所以我决定将它改为 getElementsByClassName ,并且令人惊讶的是它使用了相同的逻辑。有人可以帮我解释为什么 remove_div 不起作用,而第二个( remove_div_2 )不起作用?



注意:我没有在寻找修复/解决方案,因为我已经进行了第二个选择。我只想知道为什么 querySelectorAll 选项不起作用的原因。



以下是我的代码:



HTML:

 < div id ='container'> ; 
< div id ='div1'class ='div'>这是Div 1< / div>
< div id ='div2'class ='div'>这是Div 2< / div>
< div id ='div3'class ='div'>这是Div 3< / div>
< / div>
< button type ='button'id ='append_div'>附加div< / button>
< button type ='button'id ='remove_div'>删除Div< / button>
< button type ='button'id ='remove_div_2'>删除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 ='这是一个附加的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');
};
}


解决方案

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



鉴于 getElementsByClassName 另一方面返回一个活动的节点列表。这意味着 elToStyle [elToStyle.length - 1] 总是指向最后一个 .div ,而不考虑任何更改在节点列表准备好之后完成文档。



以下是可用的官方文档摘录 here
$ b


由querySelectorAll()方法必须是
static,而不是live([DOM-LEVEL-3-CORE],第1.1.1节)。随后的
更改为基础文档的结构不能是
反映在NodeList对象中。这意味着对象将
包含列表创建时位于
文档中的匹配元素节点列表。


注意:您可以在 console.log(elToStyle); code> removeChild 。


I have a requirement where I have to pickup the last .div within a container and apply some business logic to it. The selection of the last .div has to be dynamic because the user has the option to add/remove .div elements.

Initially I tried with querySelectorAll but it did not seem to work. So I decided to change it to getElementsByClassName and surprisingly it worked with the same logic. Can somebody please help me with the reason for why the remove_div doesn't work while the second one (remove_div_2) does?

Note: I am not looking for a fix/solution to the issue because I have already proceeded with the second option. I just want to know the reason why the option with querySelectorAll doesn't work.

Below is my code:

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');
       };
   }

解决方案

The reason is because querySelectorAll method returns a static list. Any changes made to the document after the querySelectorAll is used (like removeChild in this case) will not be reflected in the list of nodes returned. Hence elToStyle[elToStyle.length - 1] would still point to the node that was removed.

Whereas, getElementsByClassName on the other hand returns a live list of nodes. This implies that elToStyle[elToStyle.length - 1] would always point to the last .div irrespective of any changes were done to the document after the node list was prepared or not.

Below is the extract from the official documentation available here

The NodeList object returned by the querySelectorAll() method must be static, not live ([DOM-LEVEL-3-CORE], section 1.1.1). Subsequent changes to the structure of the underlying document must not be reflected in the NodeList object. This means that the object will instead contain a list of matching Element nodes that were in the document at the time the list was created.

Note: You can see this by doing a console.log(elToStyle); both before and after the removeChild.

这篇关于querySelectorAll不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆