简体   繁体   English

文档片段如何工作?

[英]how Document Fragment works?

Can anyone please explain briefly what documentFragment actually does?谁能简要解释一下 documentFragment 的实际作用? I have been searching for a clear explanation but I don't get any until now.我一直在寻找一个明确的解释,但直到现在我才得到任何解释。

what I read is, documentFragment is something like DOM like structure where we can add modify DOM elements without interrupting the actual flow of the document.我读到的是,documentFragment 类似于 DOM 结构,我们可以在其中添加修改 DOM 元素而不会中断文档的实际流程。

I also read, documentFragment is faster than appending each element into DOM one by one.我还读到,documentFragment 比将每个元素一个一个地附加到 DOM 中要快。 It felt to me like, documentFragment does not recalculate styles every time so it is faster.在我看来,documentFragment 不会每次都重新计算样式,所以它更快。

I have two examples,我有两个例子,

DOING IT IN FRAGMENT WAY:以片段方式进行:

var frag = document.createDocumentFragment();
var div1 = document.createElement("div");
var div2 = document.createElement("div");
frag.appendChild(div1);
frag.appendChild(div2);
document.getElementById("someId").appendChild(frag);

DOING IT IN NORMAL WAY:以正常方式进行:

var div = document.createElement("div");
var div1 = document.createElement("div");
var div2 = document.createElement("div");
div.appendChild(div1);
div.appendChild(div2);

document.getElementById("someId").appendChild(div);

what actually happens in the above two examples?上面两个例子中到底发生了什么?

There's an important difference between "the fragment way" and "the normal way": “片段方式”和“正常方式”之间有一个重要区别:

Using document.createElement :使用document.createElement

const div = document.createElement('div');
div.appendChild(document.createTextNode('Hello'));
div.appendChild(document.createElement('span'));
document.body.appendChild(div);
console.log(div.childNodes); // logs a NodeList [#text 'Hello', <span>]

This results in the following DOM structure:这导致以下 DOM 结构:

<body>
  <div>
    Hello
    <span></span>
  </div>
</body>

Using DocumentFragment :使用DocumentFragment

const frag = document.createDocumentFragment();
frag.appendChild(document.createTextNode('Hello'));
frag.appendChild(document.createElement('span'));
document.body.appendChild(frag);
console.log(frag.childNodes); // logs an empty NodeList

This results in the following DOM structure:这导致以下 DOM 结构:

<body>
  Hello
  <span></span>
</body>

That means that calling appendChild or insertBefore with an instance of DocumentFragment moves the child nodes of the document fragment to the new parent node.这意味着使用DocumentFragment的实例调用appendChildinsertBefore会将文档片段的子节点移动到新的父节点。 After that, the document fragment is empty.之后,文档片段为空。

As you have correctly mentioned, it can be more efficient to create a document fragment and append multiple elements to it than to append those elements to the real DOM one by one, causing the browser to re–render parts of the page every time.正如您正确提到的,创建一个文档片段并将多个元素附加到其中比将这些元素一个一个地附加到真实的 DOM 会更有效,这会导致浏览器每次重新渲染页面的一部分。 Because the contents of the document fragment are not visible on screen, the page has to be re–rendered only once.因为文档片段的内容在屏幕上是不可见的,所以页面只需要重新渲染一次。

Whenever you create a large DOM structure, it can be advisable to create it within a document fragment and append that to the DOM when you're done.无论何时创建大型 DOM 结构,都建议在文档片段中创建它,并在完成后将其附加到 DOM。

For appending only 2 childs you will not see any performance issue.对于仅附加 2 个孩子,您不会看到任何性能问题。 Imagine that you have an array of books that includes 100 items and you want to append them to the DOM.假设您有一个包含 100 个项目的书籍数组,并且您希望将它们附加到 DOM。 You would write this code:您将编写以下代码:

let books=[,,,,,,,,,,,,,,,,]
let bookList;
document.addEventListener('DOMContentLoaded',load)
 function load(){
    bookList=document.getElementById('books')
    books.forEach(book=>{
        let li=document.createElement('li')
        li.textContext=book
        li.class="bookItem"
        // here is the headache part
        bookList.appendChild(li)     
    }))
   }

So you are going to loop through 100 times and each time, you are going to tell the browser that redraw the screen.所以你要循环 100 次,每次,你要告诉浏览器重绘屏幕。 This will take up a lot of resources.这将占用大量资源。 Depending on the system that you are using, you might see the screen is flickering.根据您使用的系统,您可能会看到屏幕闪烁。

with fragment I would write load like this:使用片段我会这样写load

function load(){
     bookList=document.getElementById('books')
     let df=new DocumentFragment()
     books.forEach(book=>{
         let li=document.createElement('li')
         li.textContext=book
         li.class="bookItem"
         // we are appending to df not to the bookList
         df.appendChild(li)     
    })
    // I collected all list elements inside DocumentFragment
    // Now I append it to the bookList
    bookList.appendChild(df)
  }

creating document fragment is like creating a div .创建document fragment就像创建一个div But it does not add any Html to the page.但它不会向页面添加任何 Html。 You are not going to see in HTML source code:您不会在 HTML 源代码中看到:

 <DocumentFragment></DocumentFragment>

It is just an empty container that is used to hold other parts of Html.它只是一个空容器,用于容纳 Html 的其他部分。 we use them not to add a list of items one at a time.我们使用它们不是一次添加一个项目列表。 We are achieving exact same thing with much better performance.我们正在以更好的性能实现完全相同的目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM