Vuex 是專門為 Vue.js 設計的狀態管理庫,采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
簡單地說就是采用全局單例模式,將組件的共享狀態抽離出來管理,使組件樹中的每一個位置都可以獲取共享的狀態(變量)或者觸發行為。
額,或者更直白的說就是響應式的全局變量
State | 共享狀態(即變量) |
Getter | 基於state的派生狀態,可理解為組件中的計算屬性 |
Mutation | 更改vuex的store中狀態的唯一方法,通過提交mutation修改狀態,同步操作(規則上是不允許異步操作的,雖然異步也可以執行,但是對devtool調試的狀態跟蹤或多個狀態更改操作相互依賴是很不好的,所以不要覺得只要不報錯我就可以這么用,還是盡量按照規則來比較好) |
Action | 類似mutation,不同之處,1.通過提交mutation修改狀態 2.支持異步操作 |
Module | 模塊,在大型項目中為了方便狀態的管理和協作開發將store拆分為多個子模塊(modules),每個子模塊擁有完整的state、mutation、action、getter |
npm install vuex --save // 如果安裝了淘寶鏡像,可以使用 cnpm安裝
2.新建store.js ( 名字隨便起 ),引入vue和vuex,結構如下
在根實例中注冊store
①state--狀態
我們在state中定義屬性name,給一個初始值 “張三”;在store實例中注冊state;在組件中使用$store.state.name使用定義的屬性name
運行程序,在頁面上顯示出了我們定義的name屬性,這里我們使用的是this.$store.state來訪問vuex中定義的變量,還有一種輔助函數mapState的方式,我們在后邊再講解。好了,我們繼續,定義了狀態,我們就要對狀態進行管理,去更改狀態的值,就是下面要說的mutation
②mutation--更改store中狀態的唯一方法
之所以說唯一,是因為vuex中規定只能通過提交mutation的方式去更改store中的狀態,包括action中的操作,也是通過提交mutation去修改。
另外一點就是vuex中規定mutation中不能包含異步操作,這個在上面的核心對象中已有簡單介紹。
繼續我們的操作,直接上代碼:
(store.js) (示例組件)
效果如下:
在store.js的mutations中我們定義了兩個方法,一個是不帶參數更新name,一個是帶參數更新name。
在示例組件的methods中,我們定義了兩個方法,一個是調用無參的mutation方法,一個是調用帶參的mutation方法(包含兩種方式【載荷】、【對象】)
總結如下:
✦.mutation下事件的調用是通過 this.$store.commit 傳入對應的type調用,關於輔助函數 mapMutations 的使用在后面一期講解
✦.mutation下事件的定義分為無參的和有參的兩種形式
✦.mutation事件的調用有兩種形式,載荷和對象
③anction--異步更改狀態
上面在mutation的介紹中我們提到了,mutation中規則上是不允許異步操作的,那如果我們需要異步的進行更改狀態怎么辦?於是vuex為我們提供了action。
先上代碼:
(store.js) (示例組件)
效果:
從代碼和效果中,我們能很直觀得到兩條信息:
1.action 與 mutation 除了使用了異步操作和調用mutation,其它使用並無差別
2.異步操作時,可以明顯的看到我們設置的信息在延遲1s后發生改變
總結如下:
✦.action中不能直接更改狀態,它是通過提交mutation來實現操作
✦.它的參數是一個與 store 實例具有相同方法和屬性的 context 對象,所以可以通過context.state來獲取store中的狀態,可以通過context.commit來提交更改等
✦.action的調用使用 $.store.dispatch
✦.action事件的定義分為有參和無參兩種
✦.action事件的觸發同樣可以使用載荷和對象兩種方式
④getter--store中state的派生狀態
getter,我們可以理解為是對store中state的一些派生狀態,也可以理解為一種計算屬性,因為它像計算屬性一樣,返回值會根據它的依賴被緩存起來,且依賴對象發生改變的時候它才會被重新計算。
getter的使用對我來講就是將對store中某個屬性相同的處理操作抽出出來,做了一個公共的處理
例如,我們使用store中name的時候,需要做一個判斷:如果是張三,返回“張三最棒”,其它的原樣返回,我們可以這樣做
頁面上將 this.$store.state.name 改為 formatterName即可。但是,如果我們這個操作不只這一個組件使用,那我們就需要在每一個組件中去定義這樣一個計算屬性,且不說代碼冗余的問題,后期如果要更新后綴,想想吧,挨着一個一個組件的去巴拉。。。
而使用getter則可以很好的解決這個問題,不僅代碼簡潔,也利於維護,不多說,上getter使用代碼:
(store) (示例組件)
效果:
總結如下:
✦.getter類似計算屬性,是對store中state的一些派生狀態,可以簡化代碼、便於維護
✦.getter的使用方法 $.store.getters.屬性名
✦.getter的定義可以帶參可以不帶參
關於module,它是對store的一個分割,將store分割成一個個小的模塊,每個模塊中又具有store完整的功能。他的使用主要面向一些狀態非常多的大型應用,關於module的使用在這就不講了,有興趣可以看一下官網的介紹和講解,穿梭>>>
vuex的輔助函數有:mapState
、mapMutations
、mapGetters
、mapActions
它們的使用我們可以配合ES6的展開運算符將其與局部計算屬性或方法混合使用。使用輔助函數后我們對state、mutation、getter、actiopn的使用可以改成以下這樣:
(State => mapState)
(mutation => mapMutations)
(action => mapActions)
(getter => mapGetters)
有些小伙伴可能發現了,vuex在頁面刷新后,store中的狀態將被重新初始化,賦值的數據丟失,針對這個問題怎么處理呢? ---我們可以這樣處理,在頁面刷新或離開之前將store中的數據保存到sessionStorage 或 localStorage中,在頁面重新加載后再將數據取出,通過vuex的$store.replaceState 將數據替換到store中,上代碼
app.vue:
1 created () { 2 var store = require('store'); 3 4 //在頁面加載時讀取sessionStorage里的狀態信息 5 if (sessionStorage.getItem("storedata") ) { 6 this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("storedata")))) 7 } 8 //在頁面刷新時將vuex里的信息保存到sessionStorage里 9 window.addEventListener("beforeunload",()=>{ 10 sessionStorage.setItem("storedata",JSON.stringify(this.$store.state)) 11 }); 12 // 兼容iphone手機 13 window.addEventListener("pagehide",()=>{ 14 sessionStorage.setItem("storedata",JSON.stringify(this.$store.state)) 15 }); 16 },
好了,寫到這里吧~~,不足之處歡迎指出,好的建議感謝提出,謝過!