from:
初學者對react可能滿懷期待,覺得react可能完爆其它一切框架,甚至不切實際地認為react可能連原生的渲染都能完爆——對框架的狂熱確實會出現這樣的不切實際的期待。讓我們來看看react的官方是怎麼說的。react官方文件在advanced performanec這一節,這樣寫道:
顯然react自己也其實只是想盡量達到跟非react版本相若的效能,
react的元件渲染分為初始化渲染和更新渲染。
在初始化渲染的時候會呼叫根元件下的所有元件的render方法進行渲染,如下圖(綠色表示已渲染,這一層是沒有問題的):
但是當我們要更新某個子元件的時候,如下圖的綠色元件(從根元件傳遞下來應用在綠色元件上的資料發生改變):
我們的理想狀態是只呼叫關鍵路徑上元件的render,如下圖:
但是react的預設做法是呼叫所有元件的render,再對生成的虛擬dom進行對比,如不變則不進行更新。這樣的render和虛擬dom的對比
明顯是在浪費,如下圖(黃色表示浪費的render和虛擬dom對比)
tips:
tips:
react在每個元件生命週期更新的時候都會呼叫乙個shouldcomponentupdate(nextprops, nextstate)函式。它的職責就是返回true或false,true表示需要更新,false表示不需要,預設返回為true,即便你沒有顯示地定義 shouldcomponentupdate 函式。這就不難解釋上面發生的資源浪費了。
為了進一步說明問題,我們再引用一張官網的圖來解釋,如下圖( scu表示shouldcomponentupdate,綠色表示返回true(需要更新),紅色表示返回false(不需要更新);vdomeq表示虛擬dom比對,綠色表示一致(不需要更新),紅色表示發生改變(需要更新)):
根據渲染流程,首先會判斷shouldcomponentupdate(scu)是否需要更新。如果需要更新,則呼叫元件的render生成新的虛擬dom,然後再與舊的虛擬dom對比(vdomeq),如果對比一致就不更新,如果對比不同,則根據最小粒度改變去更新dom;如果scu不需要更新,則直接保持不變,同時其子元素也保持不變。
不論你用不用immutable,只要你想達到pure render,下面值得你注意!!!
一天我和往常一樣,開開心心得寫著react,用著@purerender,
export default class extends component =this.state; return ( person>//bug 所在
) } ... }
發現乙個問題,對於person這個子元件來說,在父元件re-render的時候,即使person得前後兩個props都沒改變,它依舊會re-render。。即使用immutable.js也不好使。。。
原來啊,父元件每次render,_handleclick都會執行bind(this)
這樣_handleclick的引用每次都會改。。所以person前後兩次props其實是不一樣的。。
那怎麼辦?把bind(this)去掉?不行 還必須得用
真正的答案是 讓父元件每次render 不執行bind(this),直接提前在定義class裡面的constructor執行好
export default class extends component render() =this.state; return ( person> div> ) } ... }
react官方提供乙個外掛程式react.addons.perf
可以幫助我們分析元件的效能,以確定是否需要優化。
開啟console面板,先輸入perf.start()
執行一些元件操作,引起資料變動,元件更新,然後輸入perf.stop()
。(建議一次只執行乙個操作,好進行分析)
再輸入perf.printinclusive
檢視所有涉及到的元件render,如下圖(官方):
或者輸入perf.printwasted()檢視下不需要的的浪費元件render,如下圖(官方):
優化前:
優化後:
react-perf-tool 為react應用提供了一種視覺化的效能檢測方案,該工程同樣是基於react.addons,但是使用圖表來顯示結果,更加方便。
var purerendermixin = require('react-addons-pure-render-mixin');
react.createclass(>foodiv>; } });
var shallowcompare = require('react-addons-shallow-compare');es7裝飾器的寫法:export class samplecomponent extends react.component render() >foo
; } }
import purerender from "pure-render-decorator"
...@purerender
class person extends component = this.props; return ( 姓名:span> span> age:span> span> div> ) } }
purerender很簡單,就是把傳進來的component的shouldcomponentupdate給重寫掉了,原來的shouldcomponentupdate,無論怎樣都是return ture,現在不了,我要用shallowcompare比一比,shallowcompare**及其簡單,如下:
function shallowcompare(instance, nextprops, nextstate)shallowequal其實只比較props的第一層子屬性是不是相同,就像上述**,props 是如下
}
他只會比較props.detail ===nextprops.detail,導致在傳入複雜的資料的情況下,優化失效。
我們也可以在shouldcomponentupdate()
中使用使用 deepcopy 和 deepcompare 來避免無必要的 render(),但 deepcopy 和 deepcompare 一般都是非常耗效能的。
immutable data 就是一旦建立,就不能再被更改的資料。對 immutable 物件的任何修改或新增刪除操作都會返回乙個新的 immutable 物件。
immutable 實現的原理是persistent data structure
(持久化資料結構),也就是使用舊資料建立新資料時,要保證舊資料同時可用且不變。同時為了避免 deepcopy 把所有節點都複製一遍帶來的效能損耗,immutable 使用了structural sharing
(結構共享),即如果物件樹中乙個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享。請看下面動畫:
immutable 則提供了簡潔高效的判斷資料是否變化的方法,只需 === 和 is 比較就能知道是否需要執行 render(),而這個操作幾乎 0 成本,所以可以極大提高效能。修改後的shouldcomponentupdate
是這樣的:
import from 'immutable';這是乙個facebook/immutable-js的react pure render mixin 的庫,可以簡化很多寫法。shouldcomponentupdate: (nextprops = {}, nextstate = {}) => , thisstate = this.state || {}; if (object.keys(thisprops).length !== object.keys(nextprops).length || object.keys(thisstate).length !== object.keys(nextstate).length) for (const key in nextprops) } for (const key in nextstate) } return false; }
使用 react-immutable-render-mixin 可以實現裝飾器的寫法。
import react from 'react';immutable 詳解及 react 中實踐import from 'react-immutable-render-mixin';
@immutablerenderdecorator class test extends react.component }
為了避免一定程度的浪費,react官方還在0.14版本中加入了無狀態元件
,如下:
// es6
const hellomessage = (props) => hello
;
大部分使用mixin和class extends的地方,高階元件都是更好的方案——畢竟組合優於繼承
。
使用es6編寫react應用(4):使用高階元件替代mixins
mixin 已死,composition 萬歲
同構基於服務端渲染,卻不止是服務端渲染。
react在減少重複渲染方面確實是有一套獨特的處理辦法,那就是virtual dom,但顯示在首次渲染的時候react絕無可能超越原生的速度,或者一定能將其它的框架比下去。因此,我們在做優化的時候,可的期待的東西有:
React 效能優化
避免重複渲染 當乙個元件的props或者state改變時,react通過比較新返回的元素和之前渲染的元素來決定是否有必要更新實際的dom。當他們不相等時,react會更新dom。在一些情況下,你的元件可以通過重寫這個生命週期函式shouldcomponentupdate來提公升速度,它是在重新渲染過...
react 效能優化
在shouldcomponentupdate 方法中判斷props和state是否改變,若未改變則無需渲染。有些情況如父元件的props或state改變了,但是子元件其實未改變,若不判斷的話會導致子元件一起被渲染。shouldcomponentupdate nextprops nextstate r...
React效能優化
一 事件的優化 1 建構函式中宣告 export default mycom extends component render fun 此中方式只會在建構函式中建立一次,效能最好,但無法傳值 2 在元件中宣告 export default mycom extends component fun 該方...