introduction
As a front-end developer, no matter whether you have used Vue
a framework as a technology stack or not, you should have heard of DOM
the concept of virtualization, also known as VDom.
Virtual DOM was first proposed by the facebook (now called Meta) technical team, and it was first used in the React framework, and then the concept of virtual DOM was introduced in Vue2.0.
The MVVM framework page rendering under the blessing of virtual DOM:
Before entering VDom, let's first understand the JavaScript operation DOM
method and performance difference;
The method and performance of JS manipulating DOM
JavaScript
The operation DOM
generally adopts the following two methods:
JavaScript
Operate directly through native codeDOM
;- Direct operation through html string splicing + innerHTML
DOM
;
native operation
When our front-end developers first contact JavaScript
, we will learn how to use native js to DOM
operate (add, delete, modify, check, event binding, etc.).
For example, there is the following code:
<div id="testEle">这是div的文本内容</div>
// 修改div的内容
const ele = documont.querySelector('#testEle');
div.innerText = "使用js-innerText修改dom文本"
// or
div.textContent = "使用js-textContent修改dom文本"
innerHtml
Use the innerHTML method
const html = `<div>使用innerHTML</div>`
div.innerHtml = html;
Virtual DOM
Here first explain what is virtual DOM, in fact, virtual DOM is 一段用来描述真实的DOM的JavaScript代码(对象)并能根据一定的规则转换成真实的DOM节点
.
Use virtual DOM to manipulate html
const virtualDOM = {
tag: 'div',
children: [{
children: '使用虚拟DOM操作html' }]
}
// render 函数将虚拟 DOM 创建为真实 DOM ,并将其插入到文档中
render(virtualDOM)
The above are the three ways of operating DOM, which are somewhat different in writing. The following focuses on analyzing performance issues;
Performance difference comparison
First, there are two important points to declare:
- The operation performance of js is far greater than that of dom, and the two of them are not in the same order of magnitude;
- The method of natively operating dom in js should remove the innerHTML method, because innerHTML is more complicated;
fastest performance
The most direct way to modify dom is to use the native method, which is also the best performance choice;
div.textContent = "使用js-textContent修改dom文本"
Because we know which part of the dom structure needs to be modified and what content to modify, it is optimal to directly use js to operate dom
Performance of Virtual DOM
Using virtual DOM to operate DOM is actually to find out DOM
the difference before and after virtualization, and then update it, please see the following sample code:
<!-- 原始的dom代码如下 -->
<div>虚拟DOM修改前</div>
<!-- 修改后的dom代码 -->
<div>虚拟DOM修改后</div>
It needs to be said here that the virtual DOM
bottom layer is still operated with native js DOM
, but we have made a layer of encapsulation for the modification. So the performance of virtualization is lower than that of DOM
native js operation ; then why do we need to add an additional layer of encapsulation here? First of all, we need to know that the biggest front-end performance is the frequent operation of the DOM. Frequent changes to the DOM will cause the browser to reflow and return. Therefore, this layer of abstraction calculates the DOM difference as much as possible during the "frequent operation" process. The final result is to ensure that the DOM will not cause performance consumption due to excessive operations. For example, when ABCAD occurs during DOM changes, direct operation of AD in VDom greatly reduces the waste of intermediate processes. From the perspective of the framework, the abstraction of DOM operations in the middle layer can liberate developers from manual operations on the DOM. At the same time, it can get more platform support in adapting to more "middle layers" and realize the cross-platform underlying support of the framework.DOM
The conclusions we can draw from the above cases are:
- Performance of native js operation
DOM
= performance of js operationDOM
; - Virtual
DOM
performance = the performance of js to find outDOM
the difference before and after +DOM
the performance of js operation;
According to the above formula, only when js找出DOM前后差异的性能
the consumption is 0, the performance of the two will be equal, but it will never exceed 原生js操作DOM的性能
, so when we use the algorithm in the framework to compare the virtual DOM
difference, it is an infinite optimization and its performance consumption Minimize (this is why diff
the algorithm is used later)
As for why virtual is still used DOM
, this question will be discussed at the end of the article.
performance of innerHTML
innerHTML
It is not a simple assignment. If the page wants to render the content of the html document, it must first parse innerHTML
the content into DOM
a structure tree, and then insert it into DOM
the document structure. Of course, the old document structure needs to be deleted before inserting. There are several key questions here:
- parse
DOM
tree - delete the original
DOM
structure - create new
DOM
structure
The above three key points 解析DOM结构树
belong to the calculation of the js level, and the other two belong to DOM
the operation calculation of the level.
Comparison of the three
Now conduct a comparative analysis of the performance consumption of the three:
Operation method | JS level | DOM level |
---|---|---|
Native JS | Pure JS operation | DOM operation |
innerHTML |
Pure JS operation html string DOM parsing |
DOM create |
virtualDOM |
create virtualDOM |
DOM create |
The above table compares the performance consumption of creating a new page, and first puts aside the native JS method (because this method has been mentioned above, it is optimal) and only compares the difference in performance loss between virtual and virtual DOM
;innerHTML
innerHTML
Performance loss = js operation html string splicing performance loss +DOM
created performance loss;- Virtual
DOM
performance loss = performance loss of js creating virtualDOM
objects +DOM
performance loss of creation;
Comparing from the dimension of creating a page alone, it seems that there is not much difference in performance between the two;
let's compare it from another dimension: 更新维度
; The process of
using innerHTML
the update page is to rebuild the html string, and then reset the attribute DOM
of the element . innerHTM
This is actually saying that even if we only change a text, we must reset innerHTML
the property. Resetting innerHTML
attributes is equivalent to destroying all old DOM
elements and creating new DOM
elements in full.
Let's look at DOM
how the virtual updates the page. It needs to recreate the javascript object (virtual DOM
), then compare the old and new virtual DOM
, find the changed element and update it.
Another factor is related to the code size of the page. For innerHTML
example, the larger the page size, the greater the performance consumption when updating. The virtual DOM
needs to update the changing part, which is related to the amount of data that needs to be updated, and has nothing to do with the page size. So the conclusion is that the larger the page, innerHTML
the greater the performance consumption, far exceeding the virtual DOM
performance consumption.
Operation method | JS level | DOM level |
---|---|---|
Native JS | Pure JS operation | DOM operation |
innerHTML |
Pure JS operation html string DOM parsing |
Destroy DOM + DOM create, related to page size |
virtualDOM |
Create a virtual DOM +Diff algorithm |
The update of the changed part DOM is related to the amount of updated data |
According to the above analysis and comparison of performance consumption, we can know: native JS < virtual DOM
< innerHTML
. So if this is the case, why don't we use native JS? This brings up another important question 可维护性
.
maintainability
Native JS operations have the best performance, but in practical business project development, we rarely use native JS to develop directly. We used to use it before, but now we use , , JQuery
and Angular
so Vue
on React
. This is mainly because it reduces the mental burden on developers and facilitates rapid development and code maintenance.
imperative
Native JS code is generally imperative, that is, what operation I want to do, I will issue any instructions, and focus on the process. A typical imperative framework (library) is JQuery, for example I want to modify the text in a label:
$('#divTag').text('修改后的文案')
Imperative code is basically one instruction after another, telling the program what I want to do. What if I want to modify the className again?
$('#divTag').className('add-class')
Declarative
The declarative style pays more attention to the result. We don’t care what the process of realization is. We just need to tell the framework the result we want, and then help me realize it. Let's implement the same code in a declarative way.
<div id="divTag" class="add-class">修改后的文案</div>
Well, this achieves the result we want, is it very readable? As for how he achieves this result, we generally don’t need to care about it, but here we still need to explain that the Vue
bottom layer is still using the imperative code to help us do the encapsulation. After all, the performance of the imperative is the best.
Summarize
When developing Vue projects, it is recommended to use template syntax, because template syntax is more intuitive than using virtual DOM directly (virtual DOM is more flexible than template syntax). The template syntax needs to be converted into a virtual DOM by a compiler, and then rendered into a real DOM node by a renderer. Compared with the traditional innerHTML, the biggest advantage of the virtual DOM is the data update section, which closely updates the changed part and consumes less performance. . In weighing performance consumption, code maintainability, Vue
(including React
, etc.) mainstream frameworks, the concept of virtualization is used DOM
. Of course, this is only part of the reason for using it, because there are also responsive and so on.