关于querySelectorAll的一个坑
刚学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,是静态的,不随文档的更新而变化。
真是愉快贴心的设计(┬_┬)