React怎麼判斷何時該從新渲染組件?

React由於他的性能而著名。由於他有一個虛擬DOM層而且只有在須要時才更新真實DOM。即便是一樣地信息這也比一直直接更新DOM要快不少。可是,React的智能僅此而已(目前爲止),咱們的任務是知道React的預期行爲以及限制,這樣咱們纔不會意外損失性能。javascript

咱們須要關注的一方面是React如何決定何時從新渲染組件。不是從新渲染DOM節點,只是調用render方法來改變虛擬DOM。咱們能夠經過告訴React何時須要渲染何時不須要渲染來幫助React。讓咱們依次來看看這些。html

1. 組件的狀態發生改變

只有在組件的state變化時纔會出發組件的從新渲染。狀態的改變能夠由於props的改變,或者直接經過setState方法改變。組件得到新的狀態而後React決定是否應該從新渲染組件。不幸的是,React難以置信簡單地將默認行爲設計爲每次都從新渲染。java

組件改變?從新渲染。父組件改變?從新渲染。一部分沒有致使視圖改變的props改變?從新渲染。react

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 (<div>...</div>);
    }
}

在這個(很是刻意的)例子中,Todo將會每秒從新渲染依次,即便render方法根本沒有使用unseen。事實上,unseen值甚至都不改變。你能夠在CodePen裏查看這個例子的實際版本。git

好吧,可是每次都從新渲染沒有什麼幫助。github

個人意思是,我很是感謝React的細心謹慎。若是狀態改變可是組件沒有正確渲染的話更糟。權衡之下,每次都從新渲染絕對是一個安全的選擇。安全

可是從新渲染的時間成本看起來很是昂貴(例子裏很是誇張地表現了出來)。性能優化

是的,在沒必要要的時候從新渲染會浪費循環而且不是一個好的想好。可是,React不能知道何時能夠安全的跳太重新渲染,因此React不管是否重要每次都從新渲染。工具

咱們如何告訴React跳太重新渲染?性能

那就是第二點要說的內容。

2. shouldComponentUpdate方法

shouldComponentUpdate方法默認返回true,這就是致使每次更新都從新渲染的緣由。可是你能夠在須要優化性能時重寫這個方法來讓React更智能。比起讓React每次都從新渲染,你能夠告訴React你何時不像觸發從新渲染。

當React將要渲染組件時他會執行shouldComponentUpdate方法來看它是否返回true(組件應該更新,也就是從新渲染)。因此你須要重寫shouldComponentUpdate方法讓它根據狀況返回true或者false來告訴React何時從新渲染何時跳太重新渲染。

當你使用shouldComponentUpdate方法你須要考慮哪些數據對與從新渲染重要。讓咱們回到這個例子。

正如你所看到的,咱們只想在titledone屬性改變的時候從新渲染Todo。咱們不關心unseen是否改變,因此我沒有把它包含在shouldComponentUpdate方法中。

當React渲染Todo組件(經過setState觸發)他會首先檢查狀態是否改變(經過propsstate)。假設狀態改變了(由於咱們顯式地調用了setState因此這會發生)React會檢查TodoshouldComponentUpdate方法。React會根據shouldComponentUpdate方法返回值爲true或者false來決定從哪裏渲染。

更新後的代碼仍然會每秒調用一次setState可是render只有在第一次加載時(或者titledone屬性改變後)纔會調用。你能夠在這裏看到。

看起來有不少工做去作。

是的,這個例子很是冗長由於有兩個屬性(titledone)須要關注而且只有一個能夠忽略(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方法讓他們更智能?試着使用性能測試工具來比較他們的性能。

相關文章
相關標籤/搜索