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