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