头图

DOM映射是前端开发中非常基础的一块内容,但是你知道吗,DOM映射是有特殊情况的。我们看个例子:
有这样一个结构

<body>
    <div></div>
</body>
let list = document.querySelectorAll('div');
document.body.appendChild(document.createElement('div'));
console.log(list); // NodeList [div]

想一下,为啥会只有一个div,按照DOM映射的机制,难道不应该两个吗?
别急,我们改行代码,就会发现答案

// querySelectorAll => getElementsByTagName
let list = document.getElementsByTagName('div');
// 以下代码没有变动
document.body.appendChild(document.createElement('div'));
console.log(list); // HTMLCollection(2) [div, div]

querySelectorAll换成getElementsByTagName之后,便会发现,现在的输出就成了我们期望的输出了。
通过这个例子我们发现querySelectorAll是DOM映射的一个特殊case。根据《JavaScript高级程序设计(第三版)》的11章11.1.2的描述我们得知:querySelectorAll返回的值实际上是带有所有属性和方法的NodeList,其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能问题。

所以我们使用这个方法的时候,在数据绑定完成后需要重新获取一次才可以。(需要注意的是,它与原先存在的元素也是映射的,也就是可以修改属性。但是新增或者删除元素不会自动反映到这个集合中)。

你可能发现了,querySelectorAll返回的是一个NodeList,getElementsByTagName返回的是HTMLCollection。
他们之间有何不同呢?这个先挖个坑,下次再讲。

那DOM映射还有其他的特殊case吗?没有了,就这一个。
顺便我们再复习一下DOM映射的内容。

什么是DOM映射

一般的,我们从页面获取的元素(包括我们创建的已经插入页面的元素)和页面中的元素是有联动关系的,只要修改一个,另一个也会跟着改变。我们把这种联动关系称之为DOM映射。
举个例子就是

1.改变元素对象的属性

这是我们最常用到的一种场景。我们修改或添加元素属性的时候,一般会从页面中获取到元素对象,对其进行修改,然后就能够自动改变页面元素的属性。

//=> 修改从页面中获取的元素样式
div.style.color = 'red';
//=> 修改已经插入页面的元素的属性
var p = document.createElement('p');
box.appendChild(p);
p.dataset.index = 1;

iShot_2024-02-23_18.36.12.gif

2. 向页面内添加元素

<body>
    <div id='box'></div>
</body>
let divList = document.getElementsByTagName('div');
document.querySelector('#box').appendChild(document.createElement('div'));
console.log(divList); // HTMLCollection(2) [div#box, div]

我们向div中插入一个div,插入前只有一个我们的集合divList中只有一个元素,插入后再次获取,里面自动就包含了我们新插入的元素。

参考文档


aqiongbei
2k 声望281 粉丝

人生路上,你走的每一步都算数