用好React,你必須要知道的事情

2022-10-10 16:36:12 字數 3933 閱讀 6712

使用react編寫元件時,我們需要有意識地將元件劃分為容器性元件(container component)和展示性元件(presentational component),這樣有助於我們在編寫元件時,更加明確這個元件應該負責哪些事情。

容器性元件,負責業務流程邏輯的處理,如傳送網路請求,處理請求資料,將處理過的資料傳遞給子元件的props使用。同時,容器性元件提供源資料的方法,以props方式傳遞給子元件,當子元件的狀態變更引起源資料的變化時,子元件通過呼叫容器性元件提供的方法同步這些變化。

展示性元件,負責元件的外表,也就是元件如何渲染,具有很強的內聚性。展示性元件不關心渲染時使用的元件屬性(props)是如何獲取到的,它只要知道有了這些props後,元件應該如何渲染就足夠了。屬性如何獲取,是容器性元件負責的事情。當展示性元件狀態的變化需要同步到源資料時,需要呼叫容器性元件中的方法,這個方法一般也是通過props傳遞給展示性元件。

例如,乙個todo專案,有乙個todo元件和乙個todolist元件,todo元件是乙個容器性元件,負責從伺服器端獲取待辦事項列表,獲取到待辦事項列表後傳遞給todolist顯示。當在todolist中新建一項待辦事項後,需要通過todolist 的 props,呼叫todo元件中儲存待辦專案的方法,將新建的待辦專案同步到伺服器端。

容器性元件和展示性元件可以相互巢狀,乙個容器性元件可以包含多個展示性元件和其他的容器性元件;乙個展示性組將也可以包含容器性元件和其他的展示性元件。這樣的分工,可以使與元件渲染無直接關係的邏輯由容器性元件集中負責,展示性元件只關注元件的渲染邏輯,從而使展示性元件更容易被復用。對於非常簡單的頁面,一般只要乙個容器性元件就足夠了;但對於負責頁面,則需要多個容器性元件,否則所有的業務邏輯都在乙個容器性元件中處理的話,會導致這個元件非常複雜,同時這個元件獲取到的源資料,可能需要經過很多層的元件props的傳遞,才能到達最終使用的展示性元件。

props、state的概念都很清晰,元件的普通屬性是指在元件中直接掛載到this下的屬性。其實,props和state也是元件的兩個普通屬性,因為我們可以通過this.props 和 this.state 直接獲取到。那麼props、state 和 元件的其他普通屬性,分別應該在什麼場景下使用呢?

props和state都是用於元件渲染的,也就是說,乙個元件最終長成什麼樣,取決於這個元件的props和state。props和state的變化都會觸發元件的render方法。但這兩者也是有區別的。props是唯讀的資料,它是由父元件傳遞過來的;而state是元件內部自己維護的狀態,是可變的。state可以根據props的變化而變化。如果元件中還需要其他屬性,而這個屬性又與元件的渲染無關(也就是render方法中不會用到),那麼就可以把這個屬性直接掛在到this下,而不是作為元件的乙個狀態。

例如,元件中需要乙個定時器,每隔幾秒改變一下元件的狀態,就可以定義乙個this.timer屬性,以備在componentwillunmount時,清除定時器。

react官網提到,this.state和this.props的更新可能是非同步的,react可能會出於效能考慮,將多個setstate的呼叫,合併到一次state的更新中。所以,不要依賴this.props 和 this.state的值計算下乙個狀態。引用官網的乙個**示例:

// wrong

this.setstate();

如果一定要這麼做,可以使用另乙個以函式作為引數的setstate方法,這個函式的第乙個引數是前乙個state,第二個引數是當前接收到的最新props。如下所示:

// correct

this.setstate(function(prevstate, props) ;

});在呼叫setstate之後,也不能立即使用this.state獲取最新狀態,因為這時的state很可能還沒有被更新,要想保證獲取到的state是最新的state,可以在componentdidupdate中獲取this.state。也可以使用帶用**函式引數版本的setstatesetstate(statechange, [callback]),**函式中的this.state會保證是最新的state。

當元件的屬性可能發生變化時,這個方法會被呼叫。這裡說可能,是因為父元件render方法每次被呼叫時,子元件的這個方法都會被呼叫(子元件第一次初始化時除外),但並不一定每次子元件的屬性都會發生變化。如果元件的state需要根據props的變化而變化,那麼這個方法就是最適合這個這個邏輯的地方。例如當props變化時,元件的state需要重置,就可以在這個方法中呼叫this.setstate()來重置狀態。需要注意,在這個方法中呼叫this.setstate()並不會重新觸發componentwillreceiveprops的呼叫,也不會導致render方法被觸發兩次。一般情況下,接收到新props會觸發一次render,呼叫this.setstate也會觸發一次render,但在componentwillreceiveprops中呼叫this.setstate,react會把原本需要的兩次render,合併成一次。

這個方法常作為優化react效能使用。當shouldcomponentupdate返回false時,元件本次的render方法不會被觸發。可以通過在這個方法中比較前後兩次state或者props,根據實際業務場景決定是否需要觸發render方法。

react提供了乙個react.purecomponent元件,這個元件重寫了shouldcomponentupdate,會對前後兩次的state和props進行淺比較,如何不一致,才會返回true,觸發後續的render方法。這裡的淺比較指,只會對state和props的第一級屬性進行比較(使用!==),這滿足一般的使用場景。如果你的元件繼承了react.purecomponent,但在setstate時,傳入的state是直接修改的原有state物件,就會因為依然滿足淺比較的條件,而不會重新觸發render方法,導致最終dom和state不一致。例如state=,在setstate時,使用this.setstate()直接修改books物件,這樣雖然books內容發生了修改,但因為物件引用並沒有變化,所以依然滿足淺比較條件,不會觸發render方法。

一般情況下,讓shouldcomponentupdate返回預設的true是不會有太大問題的。雖然這樣可能導致一些不必要的render方法被呼叫,但render方法直接操作的是虛擬dom,只要虛擬dom沒有發生變化,並不會導致實體dom的修改。而js慢是慢在實體dom的修改上。只要你的render方法不是很複雜,多呼叫幾次render方法並不會帶來多大的效能開銷。

父元件每次render方法被呼叫,或者元件自己每次呼叫setstate方法,都會觸發元件的render方法(前提是shouldcomponentupdate使用預設行為,總是返回true)。那麼元件每次render,是不是都會導致實體dom的重新建立呢?答案是,不是!

react之所以比直接操作dom的js庫快,原因是react在實體dom之上,抽象出一層虛擬dom,render方法執行後,得到的是虛擬dom,react 會把組將當前的虛擬dom結構和前一次的虛擬dom結構做比較,只有存在差異性,react才會把差異的內容同步到實體dom上。如果兩次render後的虛擬dom結構保持一致,並不會觸發實體dom的修改。

react速度快的原因,還有乙個是它出色的diff演算法。標準的比較兩棵樹的diff演算法的時間複雜是 o(n3) 。而react基於非常符合實際場景的兩個假設,就將diff演算法的時間複雜度降到了接近o(n)。這兩個假設是:

如果兩個元件或元素型別不同,那麼他們就是完全不同的樹,不需要再比較他們的子節點。例如,

和將產生是兩個完全的樹狀結構;

children

和 children

也是兩個完全不同的樹。這種情況下,元件會被完全重建,舊的dom節點被銷毀,元件經歷componentwillunmount(),然後重新建立一棵新樹, 元件經歷 componentwillmount() 和 componentdidmount()。

可以為元件或元素設定key屬性,key用來標識這個元件或元素。key不需要全域性唯一,只需要在兄弟元件或兄弟元素間保證唯一性就可以。key常用到集合(list)元素中。例如:

當在第乙個位置插入一條記錄book c 時,

由於有key的標識,react知道此時新增了一條記錄,會建立乙個新的

想用好React的你必須要知道的一些事情

前言 react 是 facebook 裡一群牛 x 的碼農折騰出的牛x的框架。實現了乙個虛擬 dom,用 dom 的方式將需要的元件秒加,用不著的秒刪。本文主要給大家介紹了關於想用好react的你必須要知道的一些事情,下面話不多說,來一起看看詳細的介紹 一 容器性元件 container comp...

外鏈代發你必須要知道的事

過去,所有的站長都認同 seo的乙個 真理 內容為王,外鏈為皇。但隨著最近幾年對內容的注重,對外鏈的打壓,外鏈的作用越來越小。而最先飽受其衝的除了各站長外,就是各外鏈代發產業了,相信為了扳回不利局面,這些代發大神也拼了命的想法子,最具有代表性的就是這句話了 外鏈的作用越來越小,說明外鏈的質量越來越重...

sizeof必須要知道的那些事

sizeof對於大多數人來說是即熟悉由陌生的。熟悉是指大家基本都用過,也知道sizeof是操作符不是函式 陌生就是指sizeof在計算自定義型別的時候,會涉及記憶體對齊方式,返回結果往往與我們想的大相徑庭。本文就是結合記憶體對齊方式來介紹如何求sizeof的返回值。先來做個測試,各位看官如能準確說出...