react《容器組件和展示組件》


作者:Dan Abramov
原文鏈接:

   https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0

容器組件和展示組件

容器組件和展示組件名詞都來自於redux中文文檔。

我在用react寫程序時,發現了一種簡單好用的模式。如果你也熟悉react,或許它早就被你發現了。有一篇文章講得很好,但是,我想補充幾點。

如果你將組件分成兩類,你會發現它們容易更被重用和理解。這兩類我稱之為容器組件和展示組件。我也聽過其他說法,比如"臃腫的"和"苗條的","智能的"和"單調的","多狀態變量"和"單純的","封裝物"和"元件"等等。概念不完全一致,卻有一樣的中心思想。

我所說的展示組件:

  • 只關心它們的樣子。
  • 可能同時包含子級容器組件和展示組件,一般含DOM標簽和自定的樣式。
  • 通常用<code>this.props.children</code>來包含其他組件
  • 不依賴app其它組件,比如flux的actions和stores
  • 不會定義數據如何讀取,如何改變
  • 只通過<code>this.props</code>接受數據和回調函數
  • 很少有自己的狀態變量,即使有,也是UI的狀態變量,比如<code>toggleMenuOpen</code>,<code>InputFocus</code>
  • 一般是函數級組件,除非它們需要狀態,lifecycle hooks,優化處理。

lifecycle hook這個詞語很形象,但我不知道怎么翻譯得貼切-_-!大概指那些監控組件生命周期里一些關鍵時刻的函數,比如,我需要在這組件初始化的時候調用某函數,那么我實現一個<code>onInit()</code>接口。react中的componentWillMount之類的函數也許也是lifecycle hook?

  • 例子有Page,Sidebar,Story,UserInfo,List

我所說的容器組件

  • 只關心它們的運作方式。
  • 可能同時包含子級容器組件和展示組件,但大都不含DOM標簽,而含他們自己所用的wrapping div,從不用自己的樣式。
  • 為展示組件或其他組件提供數據和方法。
  • 調用Flux的actions,並且將其作為展示組件的回調函數。
  • 維持許多狀態變量,通常充當一個數據源。
  • 通常由高階組件生成,比如Redux里的connect(),Relay里的createContainer(),Flux Utils里的Container.create(),而非手工寫出(譯者:可能在meteor中數據是例外吧)
  • 例子有UserPage, FollowersSidebar, StoryContainer, FollowedUserList

我把他們放在不同的文件夾中,以示區別。

這種方法的好處

  • 分離關注,你可以更好的理解app和UI。
  • 更易復用,同樣的展示組件可以在不同的狀態源、數據源中使用。也可以封裝成容器組件,在未來重用它們。
  • 展示組件是app的調色板。你可以把它們放到單獨的頁面,並讓設計師來調整它們的樣式和結構,而不用改變app的邏輯。單獨的頁面有靜態性,你可以在上面進行screenshot regression測試。
  • 這種方法會強迫你去解析布局相關的組件,比如Sidebar, Page, ContextMenu,強迫你去使用this.props.children,而非在不同容器中不斷復制jsx那塊地方。

記住,react的組件不一定要生成DOM,它們只需要考慮如何設計UI之間的分界與組合關系。利用好這一點。

什么時候引入容器?

我的建議是,你最好先做展示組件。當你意識到,有一些中間組件傳遞了過多的props,有一些組件並不使用它們繼承的props而只是將這些props傳遞給他們的子級,而且每次子級組件需要更多數據時,你都需要重新調整或編寫這些中間組件,那么,這時候你可以考慮引入容器組件了。這樣做,你可以傳遞props和方法給末端的子級組件,而不必麻煩一些不相關的中間組件。
這是一個邊寫邊改的重構,所以不必一步到位。你嘗試着這種模式,慢慢地會培養起一種對何時引入容器的直覺,就像你知道何時該增加函數一樣。我的redux教程也許會幫助你哦

其他二分法

容器組件和展示組件的分別並不被嚴格定義,理解這一點很重要。為了對比,我再列舉一些相關(但是不同的)的二分法。

多狀態變量和少狀態變量

有些組件用<code>setState()</code>,有些不用。容器組件通常多狀態變量,而展示組件卻不,這不是鐵規律。展示組件也可以多狀態變量,而容器組件也可以少狀態變量。

類與函數

自從React0.14,組件可以被聲明為類,也可以被聲明為函數。定義函數方便,卻少了類獨有的特性。有些限制或許會在未來消失,但是它們至少是存在的。因為函數容易理解,所以我推薦使用函數,除非你需要那些,現在只有類才有的狀態管理,lifecycle hooks,性能優化等特性。

純的不純的

人們說一個組件純,是指給予它一樣props和state,它保證能輸出一樣的結果。純函數可以是類,可以是函數,可以多狀態,可以無狀態。Another important aspect of pure components is that they don’t rely on deep mutations in props or state, so their rendering performance can be optimized by a shallow comparison in their shouldComponentUpdate() hook。目前只有類可以定義<code>shouldComponentUpdate()</code>,或許將來有改變吧。

展示組件和容器組件都有上述的二分特性。在我看來,展示組件傾向於少狀態、純的函數,容器組件傾向於多狀態,純的類。當然啦,這只是個人觀察,而非規則,我也見過完全相反的情況。
不要將展示組件和容器組件當作教條。有些時候,不必划出清晰的線條,也不用覺得划出區分會很困難。如果你分不清某個組件是展示組件還是容器組件,也許是為時尚早。要知道,心急吃不了熱豆腐。

那讓我們再總結一下不同點:

  展示組件 容器組件
作用 描述如何展現(骨架、樣式) 描述如何運行(數據獲取、狀態更新)
直接使用 Redux
數據來源 props 監聽 Redux state
數據修改 從 props 調用回調函數 向 Redux 派發 actions
調用方式 手動 通常由 React Redux 生成

 

文章就分享到這,歡迎關注“前端大神之路” 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM