关于querySelectorAll的一个坑

时间:2023-03-08 16:06:29

刚学JS的DOM操作时,就知道了匹配一堆元素,会获得NodeList和HTMLCollection这两个对象,不过当时并没有深入去研究两者的区别

因为无论是NodeList还是HTMLCollection,都可以用方括号来获取想要的节点,直到今天

不幸踩坑

今天写了一个网页,用AJAX向后端要数据,格式是JSON,解析后要做一个判断,看看

用来填充数据的HTML DIV元素够不够,不够用,就要调用自定义函数添加一个,直到DIV够用。

这是一个很简单的循环就能完成的事情,我隐约记得书上讲这些集合都是“动态的”

嗯?这意味着我可以这样帅气的写


 var data=JSON.parse(xhr.responseText);

 var itemArr=document.querySelectorAll('.item');

 while(itemArr.length<data.length)

 createItem();

一测试,浏览器就卡住了,很明显,这里来了一个死循环

这就意味这itemArr的length属性没有变化~~,没有我想像中的动态增长length

这明显不符合书上写的,很多书

讨论了NodeList和HTMLCollection 并不是文档状态中的一个静态快照

通常是实时,也就是说,你添加一个新的node节点,这两个对象也会变化

那我来测试一下 建立一个简单的html body里面只有一个div class='x'


 var test=document.querySelectorAll('.x');

 test instanceof NodeList //true

 test instanceof HTMLCollection //false

这说明,querySelectorAll返回的是NodeList对象

那来添加一个节点试试看


var node=document.createElement('div');

node.className='x';

document.body.appendChild(node);

test.length //还是1!

这说明,文档结构的改变,并没有影响到NodeList

既然NodeList没有任何变化,那我们来试试HTMLCollection对象吧

刷新一下浏览器

document.getElementsByClassName返回一个HTMLCollection


 var test=document.getElementsByClassName('x')

 test instanceof HTMLCollection //true

 var node=document.createElement('div');

 node.className='x';

 document.body.appendChild(node);

 test.length //2!!!!!

HTMLCollection 做到了随文档动态的变化,而NodeList在这里并没有按照动态的规则运行

这很令人费解,因为如果你使用getElementsByName方法返回的也是NodeList对象,但是这个对象的确是动态的

而这里的querySelectorAll返回的NodeList的确不是动态的。

难道问题是出现在了querySelector这个方法上?没错啊,就是querySelectorAll的毛病╮(╯_╰)╭

这个方法返回的NodeList,是静态的,不随文档的更新而变化。

真是愉快贴心的设计(┬_┬)