The most magical part of react is the virtual DOM, and its efficient diff algorithm. This allows us to "refresh" the entire page at any time without worrying about performance issues and "without scruple", by the virtual DOM to ensure that the actual DOM operation is performed only on the truly changing parts of the interface. React is transparent enough in this section, and in real-world development we don't have to worry about how virtual DOM works. However, as an attitude programmer, we are always curious about the principles behind technology. Understanding its operating mechanism not only helps to better understand the life cycle of the react component, but also helps to further optimize the react program. what is the DOM diff algorithm
The web interface is made up of a DOM tree, and when one of these parts changes, it is actually a corresponding DOM node that has changed. In react, the idea of building a UI interface is determined by the current state of the interface. Before and after two states corresponding to two sets of interfaces, and then by react to compare two interface differences, this requires the DOM tree for the diff algorithm analysis.
That is, given any two trees, find the fewest conversion steps. But the standard diff algorithm complexity requires O (n^3), which clearly does not meet performance requirements. To achieve the purpose of the interface can be refreshed at every interface, it is necessary to optimize the algorithm. This looks very difficult, but the Facebook engineers did it, they made two simple assumptions about the features of the Web interface, which reduced the complexity of the diff algorithm directly to the two identical components of O (n) to produce a similar DOM structure, with different components producing different DOM structures; For a set of child nodes of the same hierarchy, they can be distinguished by a unique ID.
The evolution of the framework of deep learning about the content of the relevant vendors -by teacher Wood Intelligent Writer--intelligent text generation in the application of double 11 deep Learning in the red Bean Live Live Recommendation System Technology and practice of Intelligent Assistant of American Regiment rider 2018, if you do not understand this technology, you may be eliminated
Related Sponsors
The optimization of the algorithm is the basis of react the whole interface render, and the fact proves that these two assumptions are reasonable and accurate, which guarantees the performance of the overall interface construction. Comparison of different node types
In order to compare between the trees, we first have to be able to compare two nodes in react, that is to compare two virtual DOM nodes, when two nodes are not the same, what should be done. There are two cases: (1) node types are different, (2) node types are the same, but properties are different. This section first looks at the first case.
When the different types of nodes are output before and after the same position in the tree, react directly deletes the previous node, and then creates and inserts a new node. Suppose we output different types of nodes two times before and after the same position in the tree.
Rendera: <div/>
renderb: <span/>
= [RemoveNode <div/>], [Insertnode <span/>]
When a node changes from Div to span, simply delete the div node directly and insert a new span node. This is in line with our understanding of real DOM operations.
It is important to note that deleting a node means destroying the node completely, instead of following the comparison to see if another node is equivalent to the deleted node. If there are child nodes under the deleted node, the child nodes are also completely deleted, and they are not used for subsequent comparisons. This is why the algorithm can be reduced to O (n) complexity.
The above refers to the operation of the virtual DOM node, and the same logic is used in the comparison of the react components, for example:
Rendera:
When react encounters different components in the same location, it is also simple to destroy the first component and add the newly created component. This is where the first hypothesis is applied, with different components typically producing a distinct DOM structure, rather than wasting time comparing the DOM structures that they are essentially not equivalent to, rather than creating a new component altogether.
It is easy to infer from this react the processing logic of different types of nodes that the DOM diff algorithm of react actually only compares the tree layer by level, as described below. node-by-layer comparison
Referring to the tree, I believe most students immediately think of is two fork tree, traverse, shortest path and other complex data structure algorithm. In react, the tree algorithm is actually very simple, that is, two trees will only be the same level of nodes to compare. As shown in the following illustration:
React will only compare DOM nodes within the same color box, that is, all child nodes under the same parent node. When the discovery node is no longer present, the node and its child nodes are completely removed and will not be used for further comparisons. This allows you to perform a single traversal of the tree, allowing you to compare the entire DOM tree.
For example, consider the following DOM structure transformation:
The A-node is moved to the D-node, the intuitive consideration of Dom diff operation should be
A.parent.remove (A);
D.append (A);
But because the react will simply consider the position transformation of the same layer node, for the nodes of different layers, only simple creation and deletion. When a root node finds a child node where a is missing, a is destroyed, and when D finds itself having a child node A, a new A is created as a child node. So the actual operation of the transformation of this structure is:
A.destroy ();
A = new A ();
A.append (New B ());
A.append (New C ());
D.append (A);
As you can see, a tree with a root node is recreated throughout.
While it may seem that this algorithm is somewhat "rudimentary", it is based on the first hypothesis: two different components typically produce a distinct DOM structure. According to React's official blog, this hypothesis has so far not led to serious performance problems. This, of course, also gives us a hint that maintaining a stable DOM structure can contribute to performance improvements when implementing your own components. For example, we can sometimes hide or show some nodes through CSS, rather than actually removing or adding DOM nodes. Understanding the lifecycle of components by Dom diff algorithm
The life cycle of the react component is described in the previous article, and each of these stages is in fact related to the DOM diff algorithm. For example, there are several methods: constructor: Constructors, which are executed when a component is created, Componentdidmount: Executes after a component is added to the DOM tree, Componentwillunmount: Executes when a component is removed from the DOM tree, The component can be considered destroyed in react; Componentdidupdate: Executed when the component is updated.
To demonstrate the relationship between the component life cycle and the DOM diff algorithm, I created an example: https://supnate.github.io/react-dom-diff/index.html, you can access the trial directly. This is when the DOM tree transitions from "shape1" to "Shape2". Let's look at the implementation of these methods:
The browser development tools console outputs the following results:
C'll unmount.
C is created.
B is updated.
A is updated.
C did mount.
D is updated.
R is updated.
As you can see, the C node is completely rebuilt and then added to the D node, rather than moving it past. If you are interested, you can fork the sample code: Https://github.com/supnate/react-dom-diff. This allows you to add additional tree structures and experiment with how they are converted. comparison of nodes of the same type
The second node comparison is the same type of node, the algorithm is relatively simple and easy to understand. The react will reset the properties to enable the conversion of the nodes. For example:
Rendera: <div id= "before"/>
renderb: <div id= "after"/>
= [replaceattribute id "after"]
The virtual Dom's style property is slightly different, its value is not a simple string and must be an object, so the conversion process is as follows:
Rendera: <div style={{color: ' Red '}}/>
renderb: <div style={{fontweight: ' Bold '}}/>
= [ Removestyle color], [Addstyle font-weight ' bold ']
Comparison of list nodes
The above describes the comparison of nodes that are not on the same layer, and even if they are identical, they are destroyed and recreated. So when they are on the same level, how do they deal with it? This involves the diff algorithm of the list node. I believe many of the students who use react have encountered such warnings:
This is the warning that react prompts when it encounters a list but cannot find the key. While ignoring this warning, most interfaces will work correctly, but this usually implies a potential performance problem. Because react felt that he might not be able to update the list efficiently.
The operations of a list node typically include additions, deletions, and sorting. For example, we need to insert node F directly into B and C, and in jquery we may use $ (B). After (f) to implement. In react, we will only tell react that the new interface should be A-B-F-C-D-E, and the update interface is done by the diff algorithm.
At this point, if each node does not have a unique identity, react cannot identify each node, then the update process will be very inefficient, that is, update C to f,d update to C,e to D, and then insert an e node. The effect is shown in the following figure:
As you can see, react will update the nodes one by one, transitioning to the target node. And finally inserting a new node E, involves a lot of DOM operations. And if you give each node a unique identifier (key), then react can find the correct location to insert the new node, as shown in the following image:
The adjustment of the order of the list nodes is also similar to inserting or deleting, and the following example code we look at the process of its transformation. Still using the example mentioned earlier: https://supnate.github.io/react-dom-diff/index.html, we convert the tree form from Shape5 to Shape6:
The position of the node at the same level will be adjusted. If a key is not provided, then react considers that the corresponding position component type after B and C is different, so after a complete deletion, the console output is as follows:
B'll unmount.
C'll unmount.
C is created.
B is created.
C did mount.
B did mount.
A is updated.
R is updated.
And if you provide a key, such as the following code:
Shape5:function () {
return (
<Root>
<A>
<b key= "B"/>
<c key= "C"/>
</A>
</Root>
);
},
shape6:function () {
return (
<Root>
<a >
<c key= "C"/>
<b key= "B"/>
</A>
</Root>
);
},
Then the console output is as follows:
C is updated.
B is updated.
A is updated.
R is updated.
As you can see, providing a unique key property for a list node can help react navigate to the correct node for comparison, greatly reducing the number of DOM operations and improving performance.