The dynamic conversion of strings to DOM nodes is often encountered in development, especially in the template engine.
String conversion to DOM node itself is not difficult, this article mainly covers two topics:
The task is to write a JavaScript function, receive a text content, dynamically generate a div containing the text, and return to that node.
1.1 Dynamic creation of Node1.1.1 InnerHTML The first method, we use the Document.createelement method to create a new element, and then use innerHTML to inject the string in, and finally return to FirstChild, to get the dynamically created node.
<script> function createNode(txt) { const template = `<div class='child'>${txt}</div>`; let tempNode = document.createElement('div'); tempNode.innerHTML = template; return tempNode.firstChild; } const container = document.getElementById('container'); container.appendChild(createNode('hello')); </script>
Now let's look at the second method
1.1.2 Domparser The Parsefromstring method of a Domparser instance can be used to convert a string directly into a Document object. With document, we can take advantage of the various DOM APIs to operate.
function createDocument(txt) { const template = `<div class='child'>${txt}</div>`; let doc = new DOMParser().parseFromString(template, 'text/html'); let div = doc.querySelector('.child'); return div; } const container = document.getElementById('container'); container.appendChild(createDocument('hello'));
1.1.2 DocumentFragment The DocumentFragment object represents a minimal document object that does not have a parent file. It is used as a lightweight version of Document to store well-formed or yet well-cared-for XML fragments. The biggest difference is that because documentfragment is not part of the real DOM tree, its changes do not cause the DOM tree to re-render the operation (Reflow), and will not cause problems such as performance.
Using the Document.createrange (). Createcontextualfragment method, we can convert a string directly into a DocumentFragment object.
function createDocumentFragment(txt) { const template = `<div class='child'>${txt}</div>`; let frag = document.createRange().createContextualFragment(template); return frag; } const container = document.getElementById('container'); container.appendChild(createDocumentFragment('hello'));
It is important to note that we directly insert the generated DocumentFragment object into the target node, which inserts all of its own points into the target node and does not contain itself. We can also use
frag.firstChild
To get the generated div.
1.1.3 Performance Test The following is a simple comparison of the performance of the above three methods, just testing the generation of a single node, in actual use does not necessarily have practical significance.
Test the CreateNode first.
function createNode(txt) { const template = `<div class='child'>${txt}</div>`; let start = Date.now(); for (let i = 0; i < 1000000; i++) { let tempNode = document.createElement('div'); tempNode.innerHTML = template; let node = tempNode.firstChild; } console.log(Date.now() - start); } createNode('hello');
Test 1 million node generation, time 6322.
Test the createdocument again.
function createDocument(txt) { const template = `<div class='child'>${txt}</div>`; let start = Date.now(); for (let i = 0; i < 1000000; i++) { let doc = new DOMParser().parseFromString(template, 'text/html'); let div = doc.firstChild; } console.log(Date.now() - start); } createDocument('hello');
Test 1 million node generation, time 55188.
Finally, test the createdocumentfragment.
function createDocumentFragment(txt) { const template = `<div class='child'>${txt}</div>`; let start = Date.now(); for (let i = 0; i < 1000000; i++) { let frag = document.createRange().createContextualFragment(template); } console.log(Date.now() - start); } createDocumentFragment();
Test 1 million node generation, time 6210.
The Createdocumentfragment method and the CreateNode method are comparable in this round of testing. Let's take a look at the methods of dynamically adding the generated DOM elements to the document.
1.2.0 adding nodes in bulk Most of the nodes that are created dynamically are added to the document and are displayed. Let's introduce and compare several common scenarios.
The following methods that we add in bulk use the Createdocumentfragment method.
1.2.1 Direct Append The direct append method is to generate a node to be added to the document, which, of course, causes a change in layout and is generally considered the worst-performing method.
const template = "<div class='child'>hello</div>"; function createDocumentFragment() { let frag = document.createRange().createContextualFragment(template); return frag; } // createDocumentFragment(); const container = document.getElementById('container'); let start = Date.now(); for (let i = 0; i < 100000; i++) { container.appendChild(createDocumentFragment()); } console.log(Date.now() - start);
The above code we calculate dynamically add 100,000 nodes. The results are as follows:
It takes 20 milliseconds to test 1000 nodes, 10001 milliseconds to test 10,000 nodes, and 100,000 milliseconds to test 46549 nodes.
1.2.2 DocumentFragment We've already covered documentfragment and used it to convert strings. Here we use this object as a temporary container to add multiple nodes at once.
Use the Document.createdocumentfragment () method to create an empty DocumentFragment object.
const template = "<div class='child'>hello</div>"; function createDocumentFragment() { let frag = document.createRange().createContextualFragment(template); return frag; } // createDocumentFragment(); const container = document.getElementById('container'); let fragContainer = document.createDocumentFragment(); let start = Date.now(); for (let i = 0; i < 1000; i++) { fragContainer.appendChild(createDocumentFragment()); } container.appendChild(fragContainer); console.log(Date.now() - start);
Testing 1000 nodes takes 25 milliseconds, 10,000 nodes take 2877 milliseconds, and 100,000 node browsers die.
1.3 Summary It is simple to introduce several methods, and there is no technical content. However, from the point of view of dynamically adding nodes, it is not true that the DocumentFragment method is much better than the direct append in my test scenario.
DocumentFragment the correct application scenario should be as a virtual DOM container, in a scene that frequently modifies queries but does not require direct rendering.
For more highlights, please follow the subscription number "Xuan said front end"