前面分別介紹完Vue的directives、options跟components後,從這天開始,我們開始要將我們備好的材料開始煮出一道道好菜了。
前面我們有提到,Vue是一個元件化為主的開發框架,所以各個元件會獨自運作,每個View去接收不一樣的元件,data也會寫在各自的元件當中去使用,但是當開發大型的系統時,可能這個頁面會去用到其他頁面的資料,不斷傳遞重複性的資料可能會造成效能變不好的狀況,所以是不是有一個規劃好的資料傳遞模式可以應用在解決這樣的問題上,下面我們要介紹一個在Vue.js中的狀態管理模式(State Manangement Pattern):Vuex。
Vuex = Vue + Flux
Vuex為官方推薦的第三方套件。
Flux是一種單向資料流的設計模式架構,應用在React進行規模化的時候。那為什麼會有Flux架構的產生?
主要是因為React是一個MVC架構中View的函式庫,每個App都需要有app state
,當使用者在View觸發事件,而系統監聽到事件後要改變狀態,狀態更動後會再去重新渲染UI,舉例像是使用者登入的狀態,它會是一個幾乎每個頁面都需要知道的狀態,因此為了解決這樣的問題,Facebook就提出了Flux這樣的設計概念,讓資料與事件能在不同頁面之間傳遞。
從上圖來看,可以看到傳遞資料的方向是單一方向的,那整個資料流是怎麼運作的?用下圖來做解釋:
Flux會幫助我們在前端開發流程上更有架構更有條理,以下是Flux的優點:
Store
,讓View
可以專注在顯示資料。前面提到Vuex是專門為Vue.js開發App專用的狀態管理模式,採用集中式儲存管理所有components的狀態,確保狀態一旦更動即會發生變化(頁面重新渲染等動作),所以也可以把Vuex當作是Vue的狀態管理庫。
我們來回憶一下前面學過的一些Vue的屬性應用,來創建一個包含事件的component。
範例:這是一個counter
<div id="app">
<counter></counter>
</div>
Vue.component ('counter', {
template: `<div>
<button @click="addCount()">CLICK</button>
<p>{{ count }}</p>
</div>`,
data: function() {
return {
count: 0
}
},
methods: {
addCount: function () {
this.count++
}
}
})
new Vue ({
el: '#app'
})
上面我們應用到template
、data
、methods
的options屬性,如此就能做出一個簡單的事件處理,而Vue簡單的狀態管理模式就如下圖所示,呈現一個單向資料流的流向:
State
:從狀態的變化回傳對應的資料給View去呈現。View
:將資料狀態呈現在使用者使用的UI上。Actions
:偵測使用者在View上觸發的行為並給予相對應的狀態變化。不過這是簡單一個元件的操作,當我們想要多個元件一起共享狀態時(例如:使用者登入狀態),下面兩種情形可能是我們會碰到的問題:
因此,為了解決以上可能會碰到的問題,我們把元件的共享狀態全部抽出來然後全局管理,Vuex這套狀態管理的架構就產生了,它參考React現下常用的Redux狀態管理模式(Redux也是基於Flux架構延伸出來的一種設計模式),一樣是單向資料流模式,是一套專門為Vue.js所設計的狀態管理庫,提高整體運作的狀態更新效能。
先理解一個概念,Vuex跟Flux有一點點不太一樣,Flux的架構包含View的重新渲染,但是Vuex處理的範圍只有上圖綠色虛線的這整塊,通過Vuex的狀態處理後,才會讓Vue去渲染元件進而產生畫面,這邊要先注意一下不要搞混了。
Vuex使用單一狀態樹(像是下圖的感覺),它最核心的概念就是把狀態(State
)儲存至Store
實體,Store
就像是一個倉庫,儲存著整個App所有的狀態。
那接下來我們就介紹在Vuex這個綠色框框中,每個角色分別所做的事情:
Actions
:
dispatch
給Actions
,接著Actions
會去commit mutation
,進而讓相對應的mutation handler
去做更改狀態的動作。Mutations
:
commit
接收Actions
傳遞的資料與行為,並經過計算處理過後改變State
。Mutation
都有一個字串型態的事件類型(type)
和一個回調函數(handler)
。回調函數(handler)
就是我們實際更改狀態的地方,第一個參數即帶入State
。commit mutation
才能改變在Store
中的狀態,這個動作就像是註冊事件一樣,是不可以直接調用mutation handler
的。State
:
Mutation
去更改狀態。Store
,但是Vuex還是保有彈性,可以讓元件保有自己的局部狀態。Actions
跟Mutations
有點相似,跟事件處理都相關,但是它們兩者還是有不一樣的地方:比較 | Actions |
Mutations |
---|---|---|
更改狀態 | Actions 只能透過commit mutation 去提交事件,不能直接更改狀態。 |
Mutations 透過mutation handler 直接實際更改狀態。 |
處理的事件種類 | 可同時處理非同步事件(call API),這樣就可以在此階段等待API回應的時間,接收到的資料再commit 給Mutations ,Mutations 收到的資料就會是即時的。 |
只能處理同步事件。 |
大致了解各個角色的定位後,我們就用一段話來整理一下它的運作流程:
當Vue.js的App使用了Vuex狀態管理庫後,整個App的幾乎所有states都會儲存至
Store
物件之中,Actions
會定義好App的所有行為,當使用者在前端View觸發事件後,Vue會去dispatch
發送行為給Actions
,Actions
接收到行為後會去commit mutation
,Mutations
接收到Actions
傳遞的行為後,會去找對應的mutation handler
並進行邏輯運算處理,直接實際更改State
物件下的某個state,當state一被更動,Vue就會收到狀態更動的訊息,即會重新render
渲染View。
前面我們大致介紹完Vuex的概念了,最後我們來總結一下Vuex適用的時機吧!
中大型網頁App開發時,如此一來就可以把狀態統一管理,開發上也可以比較方便與提高效率,而小型的較不建議,因為使用起來反而更加繁雜。
接下來幾篇我們將介紹如何安裝Vuex,並且做Vuex的實際應用。
Vuex使用單一狀態樹:就物件的資料型態來說,樹狀不是理所當然的嗎?而身為一個"global資料中心",單一也是必然的設計,且new Vue時本來就只能填入一個store。
還是我的理解有誤呢?