flux架構淺談:什麼數據才應該放store

flux架構淺談:什麼數據才應該放store

相信很多用過react和vue等框架的人都有思考過這個問題。React的出現,隨之帶來了flux這一設計理念。從React的Reflux、Redux,再到vue的vuex,一路使用過來,我覺得是該總結一下的時候了。

flux的機制已經有太多文章寫過了,這裏就不再多說。如果還不瞭解的,可以參看阮一峯的Flux 架構入門教程。這裏簡單介紹一下目前主流的三種flux架構:

Reflux是我最早接觸的flux架構,它把flux的結構簡化了,帶來了一些便利,但卻做得不夠好。它的store並不唯一,並且允許你建立多個store。如果處理不好,維護起來也是夠嗆。

Redux在這方面就做得很棒,它的store只有一個,並且引入了immutable的概念,使得store的可預測性更進一步。但是它的異步操作是痛點,雖然有如saga這種優秀的中間件,但對於新手來說,還是很容易繞暈。

vuex這方面做得挺不錯,它把異步操作限定在了actions階段,減少了很多繁瑣步驟。它的store也是唯一,但你可以在任何地方用this.$store去引用,方便的同時,對習慣不好的同學,也會帶來一些隱患。

好了,接下來我們該進入主題了。

多方觀點

前兩天,和同事在store裏面應該存放何種數據的問題上產生了分歧,於是我查了不少資料,也跟一些技術大牛進行過探討。總結起來,目前主流的觀點有兩種:

  1. store只存放公共數據,組件的數據、狀態自行維護
  2. 所有數據都應走store,view層只管展現數據,這也是flux官方所推薦的做法

這裏特別強調一下,本文所探討的是SPA應用。所以,如無特殊說明,這裏指的組件,特指頁面級組件,或者說路由級組件,並非單組件。另外,flux官方並無數據的概念,所有數據均是狀態。那我爲什麼要特意抽出來呢?後面會說。

持觀點1的人認爲:只有公共的數據、需要跨組件的數據才應放入store。優點是store小,頁面組件內的數據不必繞來繞去,開發簡單。

持觀點2的人認爲:呃,貌似我自己也差不多這種思想,爲免帶入個人思想,這裏就不妄自猜度他人想法了。

store定位

目前各方都有一定的支持人數,那麼,要理清這個問題,我們就得先把store的角色定位好。是做爲數據中心呢?還是做爲全局變量倉庫?或者還有另外的想法?

自從接觸flux以來,我也一直遵循第二種思路,但又不完全是。store是什麼?從字面上理解,就是一份存儲,一份放在本地的存儲。再來看一下我們目前的前後端交互,拉取 => 展現,再拉取 => 再展現。每切換一次頁面,都要再拉取一次數據。我們爲什麼不能做到更好呢?把store定位爲一份服務器數據本地快照如何?沒錯,這就是我的思路。

傳統應用開發,我們的應用程序都是直接和數據庫交互的。但前端不行,拋開還需要後端程序提供接口不說,前端與數據庫中間還隔着http這層,這就產生了巨大的延時。所以,爲什麼我們不能在本地建立一份數據快照?用store來做這事是不是合適?

也許你會說,localStorage、indexDB來做這事才更合適。localStorage大小且不說,你還需要藉助JSON來進行數據維護。而indexDB,操作起來也並不簡便。並且,他們的存取速度與store也明顯不是一個級別(雖然用戶幾乎感覺不到差異)。

方案

除類似autocomplate這類的sideways數據,所有從後端拉取的數據,以頁面級組件爲單位,都存入store,做爲服務器數據本地快照。這樣,當用戶切換頁面時,只有view會被銷燬。每次用戶進入該頁面,首先會拿到一份快照數據,store同時向服務器查詢最新數據。如有更新,可做提示有新數據(如新浪微博)。

而對於狀態(對,前面說了我把數據和狀態分別開來對待。數據指業務數據,而狀態,我理解爲行爲狀態),除非是全局狀態,否則,管你是頁面級組件還是單組件,自個兒內部維護。

特別說明,store裏的數據,應當儘量保持是原始的服務器數據快照,而不應該去做任何mutate,類似Redux的immutable思想。而對於add、del之類操作的結果,也不應當放入store,而只是一種狀態反饋,應當在組件內部消化。

這樣,我們的store裏就只有純粹的兩種東西:全局狀態和業務數據(服務器數據快照)。

更進一步,我們還可以藉助本地存儲把store做爲本地緩存,達到重啓app可立即恢復現場的效果。

優點

  1. 用戶體驗,對於切換頻率高的頁面,用戶體驗直線上升。設想一下,如果數據放到頁面組件內部,離開當前頁數據即被銷燬,當用戶一秒後再次返回該頁。。。
  2. 資源優化,減少對服務器的請求,對於更新週期長的數據,例如用戶個人信息,完全可以僅請求一次
  3. 可預測性,flux所提倡的數據可預測成爲可能,各種數據追蹤工具得以大展身手(微信小程序開發工具的數據追蹤就挺不錯)
  4. 可讀性,component只有view邏輯,不摻雜modal邏輯,業務邏輯清晰易維護
  5. 擴展性強,例如需要加入權限控制,進行數據過濾,在store層面就可以輕鬆解決。而如果業務數據在組件內部。。。
  6. 統一性,所有業務數據統一存取,管理方便。

缺點

再來看看持觀點1的人所反對的:

  1. store龐大,持觀點1的人首先反對的就是這個。但是,對於SPA來說,對於現代PC來說,你的SPA的store能達到以G爲單位不?
  2. 編寫繁瑣,嗯,這算一個理由吧。不過,對於其所帶來的優點來說,這點犧牲並不算什麼吧?
  3. 數據時效,有人提到,一次性數據(比如訂單結算)不應被放入store。沒錯,這點我們可以在頁面destory時手動清理不是麼?
  4. 單store文件難維護,有人提到,所有業務數據操作都在store裏,難維護。其實利用現在的構建工具,我們已經可以做到把各個頁面組件的store單獨切出來,構建時再合併,這並不會影響可維護性。
  5. 數據污染,有人擔心,這麼多數據放到store裏,會不會造成污染。對於這點,無論Redux和vuex,都是支持子store的。也就是命名空間的概念。比如 store.pageModule1、store.pageModule2。再配合一些測試工具(如mocha)做重名檢測,這方面完全不是問題

還有什麼

實際開發過程中,還有一個經常遇到的,經常被人問起的問題:公共頁面組件容易加載到非自身數據。比如文章詳情頁,如果先瀏覽了文章1,再瀏覽文章2,有可能先顯示文章1的內容,會很怪異。其實這也是一個很容易解決的問題,進入一個頁面組件時,首先加載的其實是initialState,緊接着,flux才把store裏的數據推過來。這個時候,你應該做文章id校驗,只有是自身數據,才assign。

適用場景

記得有人說過這樣的話:“如果你不知道該不該用flux,那說明你並不需要它。” Redux的作者 Dan Abramov 說:“Flux 架構就像眼鏡:您自會知道什麼時候需要它。” 如果你的業務只是需要一個全局變量倉庫,flux會不會過重?而對於大多數SPA場景,我想這個思路都是行得通的。另外,對於一次性數據比較多的應用,那這種思路或許也不太適合。

響應式store設想

我覺得最理想的狀態,flux架構還可以更進一步,把store做得更純粹一些,可以自行維護數據。具體做法是,ajax放到store層面,當請求的數據不存在或過舊時,自動拉取,而不需要通過actions來處理拉取數據的邏輯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章