Performance is certainly a big problem in how the DOM is manipulated on the page, but the clever Reactjs realizes the virtual Dom technology, which is one of his highlights. The DOM structure of the component is mapped to this virtual DOM object, and Reactjs also implements a diff algorithm, which is one of his highlights. When the component needs to be updated, the diff algorithm will be used to find the content to be changed, and finally, the update to the actual DOM node, so that the component update is not really rendering the entire DOM tree, but the update needs to modify the DOM node, so that the performance is much faster than the native DOM.
So what exactly is this virtual DOM? Suppose we want to create a component with the following structure:
1 <ul> 2 <li> 3 A 4 </li> 5 <li> 6 <ul> 7 <li> 8 B 9 </li> </ul> </li> </ul>
Then we start creating the native components:
1 //implemented with JSX.2 varroot = <ul>3<li>A</li>4<li>5<ul>6<li>7 B8</li>9</ul>Ten</li> One</ul>; A //implemented in JavaScript - varA = react.createelement (' Li ',NULL, ' A '); - varB = react.createelement (' ul ',NULL, react.createelement (' Li ',NULL, ' B ')); the varroot = React.createelement (' ul ',NULL, A, b); - //output The virtual DOM structure -Console.log (root);
Open the console and we can see the output of a JavaScript object, yes that's what we call the virtual DOM object;
Next we look at the diff algorithm in Reactjs, first we use the browser mutationobderver function, the page elements to listen to
1' Use strict ';2Const MUTATION =window. Mutationobserver3||window. Webkitmutationobserver4||window. Mozmutationobserver;5 if(!!mutation) {6Const MUTATIONOBSERVER =NewMutation (item) = {7Item.foreach (item) = {8 Console.log (item);9 });Ten }); OneConst OPTIONS = { A"Childlist":true, -"Attributes":true, -"Characterdata":true, the"Subtree":true, -"Attributeoldvalue":true, -"Characterdataoldvalue":true - }; + Mutationobserver.observe (document.body,options); -}
View Code
The life cycle of the Reactjs component is then encapsulated to make it easier for components to invoke
1' Use strict ';2Const LIFECYCLE = Name = = {3Let obj = {4 Name:name5 };6 returnobject.assign (obj,cycle);7 };8Const CYCLE = {9Getdefaultprops:function(){TenConsole.log ( This. Name, ' Getdefaultprops '); One return {}; A }, -Getinitialstate:function(){ -Console.log ( This. Name, ' Getinitailstate '); the return {}; - }, -Componentwillmount:function(){ -Console.log ( This. Name, ' Componentwillmount '); + }, -Componentdidmount:function(){ +Console.log ( This. Name, ' Componentdidmount '); A }, atComponentwillrecieveprops:function(){ -Console.log ( This. Name, ' Componentwillrecieveprops '); - }, -Shouldcomponentupdate:function(){ -Console.log ( This. Name, ' Shouldcomponentupdate '); - return true; in }, -Componentwillupdate:function(){ toConsole.log ( This. Name, ' Componentwillupdate '); + }, -Componentdidupdate:function(){ theConsole.log ( This. Name, ' Componentdidupdate '); * }, $Componentwillunmount:function(){Panax NotoginsengConsole.log ( This. Name, ' Componentwillunmount '); - } the};
View Code
Then define the components that need to be used
1' Use strict ';2 //a component3Let A =React.createclass ({4Mixins:[lifecycle (' A ')],5Renderfunction(){6Console.log (' A ', ' render ');7 return (8<ul>9<li>A</li>Ten<li> One<ul> A{ This. Props.children} -</ul> -</li> the</ul> - ); - } - }); + //B Component -Let B =React.createclass ({ +Mixins:[lifecycle (' B ')], ARenderfunction(){ atConsole.log (' B ', ' render '); - return ( -<li>B</li> - ); - } - }); in //C Components -Let C =React.createclass ({ toMixins:[lifecycle (' C ')], +Renderfunction(){ -Console.log (' C ', ' render '); the return ( *<li>C</li> $ );Panax Notoginseng } - }); the //D Components +Let D =React.createclass ({ AMixins:[lifecycle (' D ')], theRenderfunction(){ +Console.log (' D ', ' render '); - return ( $<li>D</li> $ ); - } -});
View Code
Finally, define our master logic.
1Console.log ('----------------first-----------------');2 React.render (3<a><b></b><c></c></a>,4 document.body5 );6 7SetTimeout (() = {8Console.log ('-----------------second--------------');9 React.render (Ten<A><B></B><D></D><C></C></A>, One document.body A ); -},1000);
The general practice is to remove the B and C components first, then create and insert the A,B,C components in turn. Next we open the console of the browser and see what Reactjs is doing.
As can be seen from the log, the result of the react diff algorithm is that the a component is unchanged, the C component is deleted, then the D component is created and the D component is inserted, and the C component is finally created and inserted, which eliminates the removal of the B component from our usual practice. This does not actually play the role of the diff algorithm to the limit. Let's adjust the logic code below:
1Console.log ('----------------first-----------------');2 React.render (3<a key= "A" ><b key= "B" ></b><c key= "C" ></C></A>4 document.body5 );6 7SetTimeout (() = {8Console.log ('-----------------second--------------');9 React.render (Ten<a key= "A" ><b key= "B" ></b><d key= "D" ></d><c key= "C" ></C></A>, One document.body A ); -},1000);
The main modification is to add a key property to each component, and then run the following code to see the console log:
As you can see, the diff algorithm differs greatly from the previous one. The B component does not change, and the C component does not change, except that the D component is created and inserted before the C component.
Here are some simple uses and analyses of the virtual Dom and diff algorithm, the source of learning:
http://calendar.perfplanet.com/2013/diff/ "React Native Introduction and Practice"
Why did you choose me--reactjs