摘要:我們需要關注的一方面是如何決定什么時候重新渲染組件。組件獲得新的狀態然后決定是否應該重新渲染組件。比起讓每次都重新渲染,你可以告訴你什么時候不像觸發重新渲染。重要提示當子組件的的變化時返回并不能阻止它們重渲染。
React因為他的性能而著名。因為他有一個虛擬DOM層并且只有在需要時才更新真實DOM。即使是同樣地信息這也比一直直接更新DOM要快很多。但是,React的智能僅此而已(目前為止),我們的任務是知道React的預期行為以及限制,這樣我們才不會意外損失性能。
我們需要關注的一方面是React如何決定什么時候重新渲染組件。不是重新渲染DOM節點,只是調用render方法來改變虛擬DOM。我們可以通過告訴React什么時候需要渲染什么時候不需要渲染來幫助React。讓我們依次來看看這些。
1. 組件的狀態發生改變只有在組件的state變化時才會出發組件的重新渲染。狀態的改變可以因為props的改變,或者直接通過setState方法改變。組件獲得新的狀態然后React決定是否應該重新渲染組件。不幸的是,React難以置信簡單地將默認行為設計為每次都重新渲染。
組件改變?重新渲染。父組件改變?重新渲染。一部分沒有導致視圖改變的props改變?重新渲染。
class Todo extends React.Component { componentDidMount() { setInterval(() => { this.setState(() => { console.log("setting state"); return { unseen: "does not display" } }); }, 1000); } render() { console.log("render called"); return (...); } }
在這個(非常刻意的)例子中,Todo將會每秒重新渲染依次,即使render方法根本沒有使用unseen。事實上,unseen值甚至都不改變。你可以在CodePen里查看這個例子的實際版本。
好吧,但是每次都重新渲染沒有什么幫助。
我的意思是,我非常感謝React的細心謹慎。如果狀態改變但是組件沒有正確渲染的話更糟。權衡之下,每次都重新渲染絕對是一個安全的選擇。
但是重新渲染的時間成本看起來非常昂貴(例子里非常夸張地表現了出來)。
是的,在不必要的時候重新渲染會浪費循環并且不是一個好的想好。但是,React不能知道什么時候可以安全的跳過重新渲染,所以React無論是否重要每次都重新渲染。
我們如何告訴React跳過重新渲染?
那就是第二點要說的內容。
2. shouldComponentUpdate方法shouldComponentUpdate方法默認返回true,這就是導致每次更新都重新渲染的原因。但是你可以在需要優化性能時重寫這個方法來讓React更智能。比起讓React每次都重新渲染,你可以告訴React你什么時候不像觸發重新渲染。
當React將要渲染組件時他會執行shouldComponentUpdate方法來看它是否返回true(組件應該更新,也就是重新渲染)。所以你需要重寫shouldComponentUpdate方法讓它根據情況返回true或者false來告訴React什么時候重新渲染什么時候跳過重新渲染。
當你使用shouldComponentUpdate方法你需要考慮哪些數據對與重新渲染重要。讓我們回到這個例子。
正如你所看到的,我們只想在title和done屬性改變的時候重新渲染Todo。我們不關心unseen是否改變,所以我沒有把它包含在shouldComponentUpdate方法中。
當React渲染Todo組件(通過setState觸發)他會首先檢查狀態是否改變(通過props和state)。假設狀態改變了(因為我們顯式地調用了setState所以這會發生)React會檢查Todo的shouldComponentUpdate方法。React會根據shouldComponentUpdate方法返回值為true或者false來決定從哪里渲染。
更新后的代碼仍然會每秒調用一次setState但是render只有在第一次加載時(或者title或done屬性改變后)才會調用。你可以在這里看到。
看起來有很多工作去做。
是的,這個例子非常冗長因為有兩個屬性(title和done)需要關注并且只有一個可以忽略(unseen)。根據你的數據可能僅檢查一個或兩個屬性并且忽略其他會更有意義。
重要提示
當子組件的的state變化時, 返回false并不能阻止它們重渲染。
– Facebook的React文檔
這作用于子組件的狀態而不是他們的props。所以如果一個子組件內部管理了一些他自己的狀態(使用他自己的setState),這仍然會更新。但是如果父組件的shouldComponentUpdate方法返回了false就不會傳遞更新后的props給他的子組件,所以子組件不會重渲染,即使他們的props變化了。
額外內容:簡單性能測試編寫并且在shouldComponentUpdate方法中運行計算的時間成本可能會很昂貴,所以你需要確保值得做。在寫shouldComponentUpdate方法前你可以測試React一個周期默認會消耗多少時間。有了這個信息做參考,在做性能優化時你可以做一個不盲目的決定。
使用React的性能工具去發現浪費的周期:
Perf.start() // Do the render Perf.stop() Perf.printWasted()
哪一個組件浪費了很多渲染周期?你怎么通過shouldComponentUpdate方法讓他們更智能?試著使用性能測試工具來比較他們的性能。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107176.html
摘要:所以我們做的事情其實就是,聲明了一個狀態變量,把它的初始值設為,同時提供了一個可以更改的函數。 你還在為該使用無狀態組件(Function)還是有狀態組件(Class)而煩惱嗎? ——擁有了hooks,你再也不需要寫Class了,你的所有組件都將是Function。 你還在為搞不清使用哪個生命周期鉤子函數而日夜難眠嗎? ——擁有了Hooks,生命周期鉤子函數可以先丟一邊了。 你在還...
摘要:希望大家在這浮夸的前端圈里,保持冷靜,堅持每天花分鐘來學習與思考。 今天的React題沒有太多的故事…… 半個月前出了248個Vue的知識點,受到很多朋友的關注,都強烈要求再出多些React相前的面試題,受到大家的邀請,我又找了20多個React的使用者,他們給出了328道React的面試題,由我整理好發給大家,同時發布在了前端面試每日3+1的React專題,希望對大家有所幫助,同時大...
摘要:新的值回調函數。官方注解是給組件做個標記需要重新渲染,并且將可選的回調函數添加到函數列表中,這些函數將在重新渲染的時候執行。一共做了兩件事一是通過執行方法來更新組件二是若方法傳入了回調函數則將回調函數存入隊列。 Q1 setState改變狀態之后,不會立即更新state值。所以,如果改變state值,react是什么時候進行組件的更新呢?setState()到底做了一些什么呢? A1 ...
摘要:粗讀近來沒什么特別要做的事,下班回來的空閑時間也比較多,所以抽空看看懶加載是怎么實現的,特別是看了下的庫的實現。之先別關注,按他給注釋說測試用。之是組件綁定事件時會觸發的函數。 react-lazy-load粗讀 近來沒什么特別要做的事,下班回來的空閑時間也比較多,所以抽空看看懶加載是怎么實現的,特別是看了下 react-lazy-load 的庫的實現。 懶加載 這里懶加載場景不是路由...
摘要:本系列文章將重點分析類似于的這類框架是如何實現的,歡迎大家關注和討論。作為一個極度精簡的庫,函數是屬于本身的。 前言 首先歡迎大家關注我的掘金賬號和Github博客,也算是對我的一點鼓勵,畢竟寫東西沒法獲得變現,能堅持下去也是靠的是自己的熱情和大家的鼓勵。 之前分享過幾篇關于React的文章: React技術內幕: key帶來了什么 React技術內幕: setState的秘密...
閱讀 3061·2021-11-23 09:51
閱讀 1040·2021-09-02 15:21
閱讀 3005·2019-08-30 13:56
閱讀 1829·2019-08-29 14:12
閱讀 708·2019-08-29 13:53
閱讀 1664·2019-08-29 11:32
閱讀 1325·2019-08-29 11:25
閱讀 1493·2019-08-28 17:51