文档片段以及为什么要使用它们
文档片段是文档对象模型 (DOM) 树的一个片段,是树中与 DOM 其余部分分离的一块区域。
在进一步讨论之前,我们先来谈谈浏览器重排及其对性能的影响。
根据谷歌开发者的说法,reflow 是网络浏览器重新计算文档中元素的位置和几何形状的过程的名称
,目的是重新渲染文档的部分或全部。
浏览器重排可能由调整窗口大小、
更改字体、添加或删除样式表、激活 CSS 伪类、以及脚本操作 DOM 等操作引起。
其他一些事件也可能触发浏览器重排,但我们主要关注的是脚本文件中的 DOM 操作。
让我们以从restcountries api获取的以下数据格式为例,我们需要显示每个国家及其国旗;
const countries = [
{
name: "Afghanistan",
population: 27657145,
flag: "https://restcountries.eu/data/afg.svg",
},
{
name: "Åland Islands",
population: 28875,
flag: "https://restcountries.eu/data/ala.svg",
},
{
name: "Albania",
population: 2886026,
flag: "https://restcountries.eu/data/alb.svg",
},
];
一个简单的方法是:
- 循环遍历数组中的每个元素
- 创建新元素
- 附加到 DOM 中的元素。
以下是我们在代码中实现该操作的方法。
// Select the parent element
const parentElement = document.querySelector('.countries');
// Loop over the array of countries and create each element
countries.forEach(country => {
// Create a new div element
const countryCard = document.createElement('div');
// Create a new image element
const img = document.createElement('img');
// Set the src attribute of the image to the flag value from the data
img.src = country.flag;
// Attach the image to the div we initially created
countryCard.appendChild(img);
// Attach the card to parent element
parentElement.appendChild(countryCard);
});
看起来很简单直接,而且似乎没有什么可担心的......如果它没有坏,为什么要修理它呢?😃😃。
但在底层,每次我们将 countryCard 附加到 parentElement 时,都会引起浏览器回流。在这种情况下,我们可能不会注意到任何故障或性能的急剧下降,这是因为数组中只有三个元素。现在想象一下,我们必须对 所有国家及其各自的州都
执行相同的操作……你明白这是怎么回事了吗?
幸运的是,浏览器DocumentFragment
为我们提供了一个对象。如前所述,文档片段本质上是一个
代表最小文档对象(MDN) 的接口。
它允许我们执行通常在实际 DOM 上执行的操作,
但没有通常的副作用,因此我们可以轻松创建和附加新元素,而不必担心可能
发生的大量浏览器重排,完成后,我们将片段附加回 DOM,因此只会导致一次浏览器重排,而不是如果我们不使用该片段则可能导致的数百或数千次重排。
现在,让我们重复上面提到的操作,但这次使用文档片段。我们首先需要创建片段。
这可以通过DocumentFragment
构造函数或createDocumentFragment
方法来实现。
let fragment = new DocumentFragment();
// or let fragment = document.createDocumentFragment();
const parentElement = document.querySelector('.countries');
// Loop over the array of countries and create each element
countries.forEach(country => {
// Create a new div element
const countryCard = document.createElement('div');
// Create a new image element
const img = document.createElement('img');
// Set the src attribute of the image to the flag value from the data
img.src = country.flag;
// Attach the image to the div we initially created
countryCard.appendChild(img);
// Append card to fragment element
fragment.appendChild(countryCard);
});
// After iterating, we then insert fragment contents into the DOM
parentElement.appendChild(fragment);
真正有趣的是DocumentFragment
,fragment 的内容实际上被移入了 DOM 中,只留下
一个空的DocumentFragment
。
所以你真的不用担心内存消耗……是不是很棒?😉😉
文档片段只是提升浏览器性能的众多方法之一。我们还可以采用其他一些技术来提升
Web 应用程序的性能。