Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how Document Fragment works?

Can anyone please explain briefly what documentFragment actually does? 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.

I also read, documentFragment is faster than appending each element into DOM one by one. It felt to me like, documentFragment does not recalculate styles every time so it is faster.

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?

like image 412
Jeffrin John Avatar asked Aug 07 '17 06:08

Jeffrin John


People also ask

How do I make a document fragment?

First, select the <ul> element by its id using the querySelector() method. Second, create a new document fragment. Third, for each element in the languages array, create a list item element, assign the list item's innerHTML to the language , and append all the newly created list items to the document fragment.

What the document createDocumentFragment () is?

createDocumentFragment() Creates a new empty DocumentFragment into which DOM nodes can be added to build an offscreen DOM tree.

Does React use document fragment?

Yes, it is. The external library uses document. createDocumentFragment() to create the DocumentFragment. In my React component, I call theExternalLibrary.

How do I use HTML fragments?

To create a new HTML Fragment:Click on the New HTML Fragment button at the top of the screen. In the Description box enter something descriptive so that you know what the HTML code is for or what it does. This is just for your reference and will not appear on your site. Paste your HTML code into the large HTML Code ...


2 Answers

There's an important difference between "the fragment way" and "the normal way":

Using 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:

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

Using 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:

<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. 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. 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.

like image 168
PeterMader Avatar answered Oct 08 '22 18:10

PeterMader


For appending only 2 childs you will not see any performance issue. Imagine that you have an array of books that includes 100 items and you want to append them to the 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. 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:

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. But it does not add any Html to the page. You are not going to see in HTML source code:

 <DocumentFragment></DocumentFragment>

It is just an empty container that is used to hold other parts of Html. a fragment can be injected and cloned in a single operation instead of having to inject and clone each individual node over and over again. We are achieving exact same thing with much better performance.

like image 23
Yilmaz Avatar answered Oct 08 '22 20:10

Yilmaz