爲何選擇我--ReactJS

在頁面中如何大面積操做DOM的話,性能確定是一個很大的問題,然而聰明的ReactJS實現了Virtual DOM技術,這是他的亮點之一。將組件的DOM結構映射到這個Virtual DOM對象上,而且ReactJS還實現了一套Diff算法,這也是他亮點之一。當須要更新組件的時候,會經過Diff算法找到要變動的內容,最後,在把這個修改更新到實際的DOM節點上,因此,組件更新實際上不是真的渲染整個DOM樹,而是指更新須要修改的DOM節點,這樣在性能上會比原生DOM快不少。javascript

那麼這個Virtual DOM究竟是什麼?假設咱們要建立一個組件,其結構以下:java

 1 <ul>
 2     <li>
 3         A
 4     </li>
 5     <li>
 6         <ul>
 7             <li>
 8                 B
 9             </li>
10         </ul>
11     </li>
12 </ul>

而後咱們開始建立原生組件:算法

 1 //用JSX實現的
 2 var root = <ul>
 3         <li>A</li>
 4         <li>
 5             <ul>
 6                 <li>
 7                     B
 8                 </li>
 9             </ul>
10         </li>
11     </ul>;
12 //用javascript實現的
13 var A = React.createElement('li',null,'A');
14 var B = React.createElement('ul',null,React.createElement('li',null,'B'));
15 var root = React.createElement('ul',null,A,B);
16 //輸出虛擬的DOM結構
17 console.log(root);

打開控制檯咱們就能看到輸出的一個javascript的對象,沒錯這就是咱們所說的Virtual DOM對象;瀏覽器

接下來咱們看看Diff算法在ReactJS中的體現,首先咱們藉助瀏覽器中的MutationObderver功能,對頁面元素進行監聽ide

 1 'use strict';
 2 const mutation = window.MutationObserver 
 3                 ||window.WebKitMutationObserver
 4                 ||window.MozMutationObserver;
 5 if(!!mutation){
 6     const mutationObserver = new mutation((item) => {
 7         item.forEach((item) => {
 8             console.log(item);
 9         });
10     });
11     const options = {
12         "childList" : true,
13         "attributes" : true,
14         "characterData" : true,
15         "subtree" : true,
16         "attributeOldValue" : true,
17         "characterDataOldValue" : true
18     };
19     mutationObserver.observe(document.body,options);
20 }
View Code

 而後再把ReactJS組件的生命週期進行封裝,便於組件來調用性能

 1 'use strict';
 2 const LifeCycle = name => {
 3     let obj = {
 4         name : name
 5     };
 6     return Object.assign(obj,Cycle);
 7 };
 8 const Cycle = {
 9     getDefaultProps:function(){
10         console.log(this.name,'getDefaultProps');
11         return {};
12     },
13     getInitialState:function(){
14         console.log(this.name,'getInitailState');
15         return {};
16     },
17     componentWillMount:function(){
18         console.log(this.name,'componentWillMount');
19     },
20     componentDidMount:function(){
21         console.log(this.name,'componentDidMount');
22     },
23     componentWillRecieveProps:function(){
24         console.log(this.name,'componentWillRecieveProps');
25     },
26     shouldComponentUpdate:function(){
27         console.log(this.name,'shouldComponentUpdate');
28         return true;
29     },
30     componentWillUpdate:function(){
31         console.log(this.name,'componentWillUpdate');
32     },
33     componentDidUpdate:function(){
34         console.log(this.name,'componentDidUpdate');
35     },
36     componentWillUnmount:function(){
37         console.log(this.name,'componentWillUnmount');
38     }
39 }; 
View Code

接着定義須要用到的組件學習

 1 'use strict';
 2 //A組件
 3 let A = React.createClass({
 4     mixins:[LifeCycle('A')],
 5     render:function(){
 6         console.log('A','render');
 7         return (
 8             <ul>
 9                 <li>A</li>
10                 <li>
11                     <ul>
12                         {this.props.children}
13                     </ul>
14                 </li>
15             </ul>
16         );
17     }
18 });
19 //B組件
20 let B = React.createClass({
21     mixins:[LifeCycle('B')],
22     render:function(){
23         console.log('B','render');
24         return (
25             <li>B</li>
26         );
27     }
28 });
29 //C組件
30 let C = React.createClass({
31     mixins:[LifeCycle('C')],
32     render:function(){
33         console.log('C','render');
34         return (
35             <li>C</li>
36         );
37     }
38 });
39 //D組件
40 let D = React.createClass({
41     mixins:[LifeCycle('D')],
42     render:function(){
43         console.log('D','render');
44         return (
45             <li>D</li>
46         );
47     }
48 });
View Code

最後,定義咱們的主邏輯this

 1 console.log('----------------first-----------------');
 2 React.render(
 3     <A><B></B><C></C></A>,
 4     document.body
 5 );
 6 
 7 setTimeout(() => {
 8     console.log('-----------------second--------------');
 9     React.render(
10         <A><B></B><D></D><C></C></A>,
11         document.body
12     );
13 },1000);

常規的作法就是將B和C組件先刪除,而後依次建立和插入A,B,C組件。接下來咱們打開瀏覽器的控制檯看下ReactJS是怎麼作的         spa

           

從日誌中能夠看出,React的Diff算法的結果是,A組件不變,先將C組件進行刪除,而後在建立D組件並插入D組件,最後建立並插入C組件,這比咱們常規的作法省去了對B組件的刪除操做。這樣其實並無將Diff算法的做用發揮到極限。下面咱們調整下邏輯代碼:3d

 1 console.log('----------------first-----------------');
 2 React.render(
 3     <A key="A"><B key="B"></B><C key="C"></C></A>,
 4     document.body
 5 );
 6 
 7 setTimeout(() => {
 8     console.log('-----------------second--------------');
 9     React.render(
10         <A key="A"><B key="B"></B><D key="D"></D><C key="C"></C></A>,
11         document.body
12     );
13 },1000);

主要的修改就是給每一個組件加了一個key屬性,此時再來運行下代碼看下控制檯的日誌:

       

能夠看出,此次Diff算法與以前的有很大的不一樣。B組件不變,C組件不變,只是在C組件以前建立並插入了D組件。

以上即是Virtual DOM和Diff算法的一些簡單的使用和分析,學習來源:

http://calendar.perfplanet.com/2013/diff/ 《React Native入門與實踐》

相關文章
相關標籤/搜索