preface

First of all, welcome everyone to pay attention to my Nuggets account and Github blog, which can also be regarded as a little encouragement to me. After all, there is no way to make money by writing things, and it is my enthusiasm and everyone’s encouragement that can persist.

The main reason why I want to write this series of articles is that I haven’t written anything for nearly a month, and I don’t have much time to study my favorite things because of a lot of things recently. Some time ago, I read the blog of Livoras, who explained the Virtual DOM very thoroughly. As I am engaged in React development and also a Virtual DOM user, I started to write a series of articles about the Virtual DOM. I also want to try to implement a Virtual DOM on my own. Therefore, this series of articles will focus on the topic of Virtaul DOM to do a series of analysis and even try to implement their own Virtual DOM framework with you. Interested students can follow my nuggets account or follow my Github blog.

Framework to review

First of all, I heard that the concept of Virtual DOM came from React, and when I didn’t understand it, I felt that this concept was a very high word. In fact, the birth of any technology has a corresponding history, nothing appears out of thin air, just like I heard many people criticize the syntax of JavaScript language too much dross, But in essence, you wouldn’t think so when you look at the reason for JavaScript’s existence and its author, Brendan Eich, designing a wildly popular high-level language in just a dozen days. Similarly, the Virtual DOM has a history, which has to go back to the history of front-end frameworks.

In fact, all the things that the framework can do can be achieved manually. When we learn JavaScript in college classes (of course, there are no relevant courses) and want to create a form verification program with JavaScript, more than ten lines of code can be done. Frames are bloated and unnecessary to you. Even frameworks can dramatically increase your learning costs and slow down the speed of your programs (frameworks are not guaranteed to be more efficient than your manual approach). But as your application gets bigger and your code expands exponentially, to tens of thousands of lines in a SINGLE JS file (don’t be surprised, I’ve actually seen this happen), maintaining that code can be a disaster.

This is where front-end frameworks come in, not for performance, but for maintainability and team development. But there is no such thing as a free lunch. You have to compromise some performance for the sake of maintainability. After all, no framework has better performance than manual native operation, because frameworks have to be adaptable and can handle a wide variety of scenarios.

MVC

In fact, what the front end needs to do is to display the data interface (View) and the change in the interface can trigger the corresponding data (Model) changes, and when the data (Model) changes, the interface (View) can also respond in time and make corresponding changes. It’s all about reconciling View and Modal.

Early frameworks like Backbone are typical MVC(in fact, I have not experienced this era). By setting up the Controller layer in the View and Model, the actions triggered by user interaction will be transferred to the Controller, and the Controller layer will control the corresponding data that changes the Model. When the Model data changes, it will notify the corresponding View through the observer mode, and then the View will request the Model data to make the corresponding interface change again.

As the application scale increases, you will find several significant problems in the MVC pattern. The mapping between Model and View is many-to-many. A Model may correspond to multiple views or a View to multiple Models, or even more complex scenes. The complex relationship between Model and View makes development more difficult. And because views are model-dependent, it is relatively difficult to componentize views in this mode.

MVP

We didn’t want the View and Model to be so dependent on each other, so we could improve the MVC Model, and we had the MVP Model.

In this way, the Model and View can be independent of each other through Presenter. As long as the interface between the View and Model is reserved, the two have no influence on each other and are transparent to each other. On this basis, it is very easy to realize the componentization of the View. However, this Model is not without its drawbacks. The Presenter logic not only needs to assume all the functions of the previous Controller, but also needs to receive notification of changes in Model data and change the user interface according to the corresponding functions, which makes the Presenter assume too many functions. Makes presenters too bloated to maintain.

MVVM

We found that MVP also has corresponding shortcomings, so predecessors made improvements on the basis of MVP, the emergence of the STRUCTURE of MVVM.

The advantages of MVVM are obvious, as the maintainability is greatly improved, and the mutual manual maintenance updates between the View and Model are freed up and replaced with automatic updates. However, because viewModels are relatively expensive to build and maintain, they are not suitable for some simple pages and incur performance costs for complex views.

Let’s do it another way

So far we have seen how the MV* type framework addresses the connection between the Model layer and the View layer by building various intermediate layers (Controller, Presenter, View of Model) between the Model and View to handle the synchronization between the two. But can we think of the View as a regular View representation of the Model, so when the Model changes, we just re-render the View.

We can’t help but feel this way of operation is really SAO ah!

Will this approach work? Of course! Isn’t that the whole idea of React? But as an experienced person, you will immediately question whether this thing is reliable. In fact, if the Model changes and the View changes a lot (such as all the interface changes), this mode can actually perform well, because the interface changes themselves are equivalent to re-rendering. But if the current Model changes only caused a very subtle change in the interface (such as the color of a button changing), we would have to refresh the entire interface, which would have been horrible.

Those of you who have been involved in the front-end must understand that the speed of DOM is simply turtle speed compared to JavaScript, because the DOM properties and structure itself are very complex. Can this approach be scrapped altogether?

No! React wouldn’t have happened otherwise.

Those who have studied the principle of computer composition in university should remember that CPU’s calculation speed is very fast, but compared with CPU, other IO components, such as hard disk, speed is very low, the difference is not an order of magnitude problem. At this time, the computer introduced RAM, RAM speed is lower than CPU but higher than the hard disk, for THE CPU required data, you can first put into RAM from the hard disk, and then CPU calculation results are also put into RAM, if the need for data storage will be stored in the hard disk. Even the CPU found RAM slow and introduced levels of caches inside the CPU to solve the performance bottleneck between RAM and CPU.

The front-end can take advantage of this mindset. DOM is slow, but JavaScript performance is pretty good, especially today with a V8 engine. We can then use JavaScript to describe the DOM structure, similar to the following:

The DOM structure described here looks like this:

<div>
    <button>button</button>
</div>
Copy the code

Of course, this notation is not unique, but you can use it as long as you can describe the corresponding DOM structure.

In this way, after each Model change, we can first get the corresponding Virtual DOM structure of the Model, which represents the DOM structure of the View corresponding to the Model. If we also cache the Virtual DOM structure corresponding to the Model last time in the program, then we can compare the two Virtual DOM structures before and after and use a certain algorithm to find out the inconsistency between the two Virtual DOM structures. This algorithm is commonly referred to as the Diff algorithm. Then the differences between the two Virtual DOM are applied to the real DOM in an optimal way.

Is this definitely a better idea than the re-rendering we talked about in the beginning? Of course not. If the interface changes significantly, then the performance of the Virtual DOM we talked about earlier may be lower than that of re-rendering, because the Diff process also has a performance penalty. Even when React uses various heuristic algorithms to reduce the two Virtual DOM tree structures from O(n ^ 3) to O(n), the cost of Diff should be considered in the case of very many nodes.

conclusion

In this article, we take a quick look at the evolution history of various MV* frameworks to explain another set of novel solutions proposed by React and why React introduced the Virtual DOM. Read here may have some help for you to understand Virtual DOM, welcome to pay attention to my blog, will continue to update the Virtual DOM series of articles and other I learned in the front end. If there is any incorrect place, welcome to comment.