摘要:在下一次渲染時,新的樹會被生成,接著就是對比兩棵樹。官方一點的定義應該稱為,也就是用來比較兩棵節點樹的算法,它確定樹中的哪些部分需要被更新。終于說到,他是一個組件的方法,用于攔截組件渲染。讓我們用例子解釋所謂攔截渲染。
原文鏈接:https://ssshooter.com/2019-03...
我曾經對 shouldComponentUpdate 的用途不解。react 的賣點之一,是通過 diff 虛擬節點樹,減少對真實節點的操作,所以我以前以為既然 diff 了,那就自然知道節點有沒有更新了,diff 是根據 setState 的內容進行的,那 shouldComponentUpdate 有什么用呢?
然而我以前的理解是完全錯誤的,造成這個疑問的原因便是對 React 渲染流程的不熟悉。從頭說起。
setState你修改了數據,需要 React 重新渲染頁面,讓你的新數據展示在頁面上,需要借助 setState 方法。
setState 調用后,組件的 render 方法也會自動調用,這就是為什么你能在頁面看到新數據。但是無論你 setState 修改的是什么,哪怕是頁面里沒有的一個數據,render 都會被觸發,并且父組件渲染中會嵌套渲染自組件。
class Nest extends React.Component { render() { console.log("inner") returnNest} } class App extends React.Component { render() { console.log("outer") return () } }
所以在這個例子中,點擊按鈕,即使修改的 anything 根本沒有出現,甚至沒有定義,render 函數還是如期運行。每次點擊按鈕,上面的代碼會先輸出 outer,然后輸出 inner。
renderrender 生成的是什么呢?一般來說大家都是寫 jsx,所以視覺上是一個“dom”,但是實際上,官網也在顯眼的位置告訴你,這其實是一個函數。
// jsx const element =Hello, world!
// babel 轉換為瀏覽器能運行的函數 const element = React.createElement( "h1", { className: "greeting" }, "Hello, world!" )
而因為 React 的組件層層嵌套,render 函數會生成一棵描述應用結構的節點樹,并保存在內存中。在下一次渲染時,新的樹會被生成,接著就是對比兩棵樹。
diff官方一點的定義應該稱為 reconciliation,也就是 React 用來比較兩棵節點樹的算法,它確定樹中的哪些部分需要被更新。
在確定兩棵樹的區別后,會根據不同的地方對實際節點進行操作,這樣你看到的界面終于在這一步得到了改變。當年 React 也就因為這個高效的 dom 操作方法得到追捧。
shouldComponentUpdate終于說到 shouldComponentUpdate,他是一個組件的方法,用于攔截組件渲染。讓我們用例子解釋所謂“攔截渲染”。
class Nest extends React.Component { shouldComponentUpdate = () => { // <---- 注意這里 return false } render() { console.log("inner") returnNest} } class App extends React.Component { render() { console.log("outer") return () } }
跟之前的例子差不多,不過當我們在子組件添加 shouldComponentUpdate 后,再點擊按鈕,結果是 ————
沒錯,子組件的渲染函數并沒有調用,借助 shouldComponentUpdate 返回 false,成功攔截了子組件的渲染。
當然一般不會這么做,因為永遠返回 false 的話這個組件(當然因為渲染函數沒有運行,所以包括其所有子組件都是不會更新的)就永遠不會更新了。
常用操作是,在 shouldComponentUpdate 判定該組件的 props 和 state 是否有變化,就像這樣:
class Nest extends React.Component { shouldComponentUpdate = (nextProps, nextState) => { return ( !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState) ) } render() { console.log("inner") returnNest} }
這樣可以淺比較 props 和 state 是否有變化,至于為什么不深比較?因為那樣效率可能會比直接全都運行 render 還低...
因為上面的操作太常見,React 直接為我們提供了 PureComponent:
class Nest extends React.PureComponent { render() { console.log("inner") returnNest} }
使用 PureComponent 的效果就與上面淺比較一樣,并且省掉了 shouldComponentUpdate。
什么時候用?PureComponent 能提高性能!所以直接用 PureComponent 代替所有 Component!
這當然是錯的。
對于明知道不需要修改的組件,肯定直接返回 false。而可能你沒想到,對于明知道需要修改的組件,也請不要使用 PureComponent。
因為正如上面所說,PureComponent 需要進行兩次淺比較,而淺比較也是要時間的,若是你明知道這個組件百分百要修改,何必浪費時間去對比呢?
所以 PureComponent 請用在較少進行修改的組件上。
總結總結一下以上內容,整個流程基本如下:
本文部分存在個人理解,如果文中有不嚴謹的地方,請在評論區指出,謝謝大家的閱讀。
參考文獻:
https://reactjs.org/docs/faq-...
https://reactjs.org/docs/opti...
https://github.com/xitu/gold-...
https://cdb.reacttraining.com...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109207.html
摘要:如果組件是純函數的,就是給組件相同的和組件就會展現同樣的,可以使用這個來優化組件的性能。僅用于擁有簡單和的組件。雖然提供簡單的來提升性能,但是如果有更特殊的需求時怎么辦如果組件有復雜的和怎么辦這個時候就可使用來進行更加定制化的性能優化。 React: 一個用于構建用戶界面的JAVASCRIPT庫. React僅僅專注于UI層;它使用虛擬DOM技術,以保證它UI的高速渲染;它使用單向數據...
摘要:對同一層級的子節點進行處理時,會根據進行簡要的復用。或者直接使用,原理一致。 一、從React原理談起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于構建用戶界面的JS框架。因此react只負責解決view層的渲染。 react做了什么? Virtual Dom模型 生命周期...
摘要:應用主要的的性能瓶頸來自于一些冗余的程序處理以及組件中的的過程。為了避免這種情況,在你的應用中盡可能多的讓返回。使用工具將幫助你找到應用程序中特定的性能問題。這個工具跟用起來很像,但是它是專門用來檢測應用性能的。 這段時間對自己寫的React應用的性能做了一些分析以及優化,發現項目中產生性能問題的原因主要來自兩個方面: 大量的數據渲染使組件進行不必要的diff過程,導致應用卡頓; 部...
摘要:唯一不足的是,這種開發方式容易造成注入等安全問題。其中,最棘手的是如何再現中的更新機制。換句話來說,節點是包含狀態的。對于沒有改變的節點,讓它保持原樣不動,僅僅創建并替換變更過的節點。是樹形結構,所以算法必須是針對樹形結構的。 本文主要講述 React 的誕生過程和優化思路。 內容整理自 2014 年的 OSCON - React Architecture by vjeux,雖然從今天...
摘要:寫在開頭從頭實現一個簡易版二地址在上一節,我們的已經具備了渲染功能。參考資料,感謝幾位前輩的分享陳屹深入技術棧 寫在開頭 從頭實現一個簡易版React(二)地址:https://segmentfault.com/a/11...在上一節,我們的react已經具備了渲染功能。在這一節我們將著重實現它的更新,說到更新,大家可能都會想到React的diff算法,它可以說是React性能高效的保...
閱讀 3588·2021-09-13 10:28
閱讀 1937·2021-08-10 09:43
閱讀 1010·2019-08-30 15:44
閱讀 3178·2019-08-30 13:14
閱讀 1830·2019-08-29 16:56
閱讀 2938·2019-08-29 16:35
閱讀 2843·2019-08-29 12:58
閱讀 864·2019-08-26 13:46