相信不少用過react和vue等框架的人都有思考過這個問題。React的出現,隨之帶來了flux這一設計理念。從React的Reflux、Redux,再到vue的vuex,一路使用過來,我以爲是該總結一下的時候了。html
flux的機制已經有太多文章寫過了,這裏就再也不多說。若是還不瞭解的,能夠參看阮一峯的Flux 架構入門教程。這裏簡單介紹一下目前主流的三種flux架構:前端
Reflux是我最先接觸的flux架構,它把flux的結構簡化了,帶來了一些便利,但卻作得不夠好。它的store並不惟一,而且容許你創建多個store。若是處理很差,維護起來也是夠嗆。vue
Redux在這方面就作得很棒,它的store只有一個,而且引入了immutable的概念,使得store的可預測性更進一步。可是它的異步操做是痛點,雖然有如saga這種優秀的中間件,但對於新手來講,仍是很容易繞暈。react
vuex這方面作得挺不錯,它把異步操做限定在了actions階段,減小了不少繁瑣步驟。它的store也是惟一,但你能夠在任何地方用this.$store去引用,方便的同時,對習慣很差的同窗,也會帶來一些隱患。ajax
好了,接下來咱們該進入主題了。vuex
前兩天,和同事在store裏面應該存放何種數據的問題上產生了分歧,因而我查了很多資料,也跟一些技術大牛進行過探討。總結起來,目前主流的觀點有兩種:數據庫
store只存放公共數據,組件的數據、狀態自行維護小程序
全部數據都應走store,view層只管展示數據,這也是flux官方所推薦的作法後端
這裏特別強調一下,本文所探討的是SPA應用。因此,如無特殊說明,這裏指的組件,特指頁面級組件,或者說路由級組件,並不是單組件。另外,flux官方並沒有數據的概念,全部數據均是狀態。那我爲何要特地抽出來呢?後面會說。微信小程序
持觀點1的人認爲:只有公共的數據、須要跨組件的數據才應放入store。優勢是store小,頁面組件內的數據沒必要繞來繞去,開發簡單。
持觀點2的人認爲:呃,貌似我本身也差很少這種思想,爲免帶入我的思想,這裏就不妄自猜度他人想法了。
目前各方都有必定的支持人數,那麼,要理清這個問題,咱們就得先把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可當即恢復現場的效果。
用戶體驗,對於切換頻率高的頁面,用戶體驗直線上升。設想一下,若是數據放到頁面組件內部,離開當前頁數據即被銷燬,當用戶一秒後再次返回該頁。。。
資源優化,減小對服務器的請求,對於更新週期長的數據,例如用戶我的信息,徹底能夠僅請求一次
可預測性,flux所提倡的數據可預測成爲可能,各類數據追蹤工具得以大展身手(微信小程序開發工具的數據追蹤就挺不錯)
可讀性,component只有view邏輯,不摻雜modal邏輯,業務邏輯清晰易維護
擴展性強,例如須要加入權限控制,進行數據過濾,在store層面就能夠輕鬆解決。而若是業務數據在組件內部。。。
統一性,全部業務數據統一存取,管理方便。
再來看看持觀點1的人所反對的:
store龐大,持觀點1的人首先反對的就是這個。可是,對於SPA來講,對於現代PC來講,你的SPA的store能達到以G爲單位不?
編寫繁瑣,嗯,這算一個理由吧。不過,對於其所帶來的優勢來講,這點犧牲並不算什麼吧?
數據時效,有人提到,一次性數據(好比訂單結算)不該被放入store。沒錯,這點咱們能夠在頁面destory時手動清理不是麼?
單store文件難維護,有人提到,全部業務數據操做都在store裏,難維護。其實利用如今的構建工具,咱們已經能夠作到把各個頁面組件的store單獨切出來,構建時再合併,這並不會影響可維護性。
數據污染,有人擔憂,這麼多數據放到store裏,會不會形成污染。對於這點,不管Redux和vuex,都是支持子store的。也就是命名空間的概念。好比 store.pageModule一、store.pageModule2。再配合一些測試工具(如mocha)作重名檢測,這方面徹底不是問題
實際開發過程當中,還有一個常常遇到的,常常被人問起的問題:公共頁面組件容易加載到非自身數據。好比文章詳情頁,若是先瀏覽了文章1,再瀏覽文章2,有可能先顯示文章1的內容,會很怪異。其實這也是一個很容易解決的問題,進入一個頁面組件時,首先加載的實際上是initialState,緊接着,flux才把store裏的數據推過來。這個時候,你應該作文章id校驗,只有是自身數據,才assign。
記得有人說過這樣的話:「若是你不知道該不應用flux,那說明你並不須要它。」 Redux的做者 Dan Abramov 說:「Flux 架構就像眼鏡:您自會知道何時須要它。」 若是你的業務只是須要一個全局變量倉庫,flux會不會太重?而對於大多數SPA場景,我想這個思路都是行得通的。另外,對於一次性數據比較多的應用,那這種思路或許也不太適合。
我以爲最理想的狀態,flux架構還能夠更進一步,把store作得更純粹一些,能夠自行維護數據。具體作法是,ajax放到store層面,當請求的數據不存在或過舊時,自動拉取,而不須要經過actions來處理拉取數據的邏輯。