在實際開發項目中,我將所有的React組件划分為容器組件和展示組件,展示組件其實就是一個純函數組件,沒有任何副作用,基本都是PureComponent。但是突然,出現了這么一個問題:
我有一個浮層組件Layer,它是一個展示信息明細的面板類似於這種,就比如訂單下單之后,在價格邊上有個查看明細,這時候點擊就會彈出該浮層。我有多個頁面要用到類似的浮層,因此我毫不猶豫地將它單獨抽離出來。它的內容以及是否展示,由它的props來決定,也就是在容器組件內部。
但是我發現兩個問題:
1,雖然浮層展示是由外部控制,但是浮層隱藏卻是由浮層自己控制,比如點擊浮層內部某個按鈕它自動消失,那這樣有兩個方式:
第一,把點擊消失的事件也放到外層,但是其實所有浮層組件的消失事件都是一樣的,就是讓它隱藏而已,如果每次調用該組件都要重復定義該動作,有些浪費。
第二,把點擊消失的事件放到組件內部,然后用state來控制,至於組件展示的props,可以通過生命周期函數componentWillReceiveProps來控制state,但是這樣的話又顯得這個組件非常復雜,既有外部狀態,又有內部狀態,而且考慮到v16.3版本后該生命周期函數會被廢掉,又要考慮其它的。。。
2,當容器組件非常復雜時,我為了展示一個浮層,卻要把整個容器組件都re-render一遍,似乎有點因小失大。
當時我的項目技術選型,數據流管理用的是mobx,於是我決定,將它單獨與一個layerStore來進行映射,它的狀態監聽全部放在store里,包括點擊事件,這樣有個好處是相當於我這個浮層組件已經脫離任何調用它的組件了,因為它的狀態和事件都和那些組件無關了,它只取決於自己的store,只不過我可以在需要調用它的時候,在外部組件的事件里多寫一行:layerStore.showLayer();
但是這種方式的壞處就是:
1,這個組件無法做到復用到其他項目中(如果別的項目沒有用mobx,那這種綁定store的方式也就廢棄了);
2,這個組件成了一個真正意義上的‘公共’組件,它不屬於某個組件內的,因為它的store是公共的。我們看似公用了一個組件,但實際上,都是在操作一個store,沒有辦法同時存在兩個不同狀態的Layer。
想到這兒,我的糾結症已經快令我抓狂了。到底哪種實現方式最佳?最終我還是選擇了后者,因為在當前項目中,后者一定更優一些,因為我們不存在兩個浮層同時出現的情況。那如何選擇實現方式,實際上是看你對組件的理解了,角度不同,實現方式自然不同。就像這個浮層組件,如果你理解的它是每個組件都擁有各自的浮層,那么你應該會選擇前者,如果你理解的它是唯一一個,是公用的,它就藏在屏幕下面,只是不停地改變樣子罷了,那你應該選擇后者。
最后,依然要考慮到性能問題,不要撿了芝麻,丟了西瓜。