Vuex的初探與實戰小結
1.概述
每一個 Vuex 應用的核心就是 store(倉庫)。“store”基本上就是一個容器,它包含著你的應用中大部分的狀態 (state)。
Vuex 和單純的全域性物件有以下兩點不同:
1.Vuex 的狀態儲存是響應式的。當 Vue 元件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的元件也會相應地得到高效更新;2.你不能直接改變 store 中的狀態。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地瞭解我們的應用
**2.安裝使用 **
2.1.使用Vue-cli開發安裝vue包
cnpm install vuex --save
2.2.在src目錄下建立store資料夾並建立index.js如下(src/store/index.js)
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); export default new Vuex.Store({ state: { }, getters: { }, mutations: { }, actions: { } });
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,群內有大量PDF可供自取,更有乾貨實戰專案視訊進群免費領取。
然後在src檔案下的main.js中使用
import Vue from 'vue' import App from './App' import store from './store' Vue.config.productionTip = false new Vue({ el: '#app', store, components: { App }, template: '<App/>' })
3.用法簡介
** 3.1.state**
state是儲存共享資料的,現在改store/index.js如下:
state: { count:0 },
在components目錄下建立Index.vue如:
<template> <div class="index"> {{count}} </div> </template> <script> export default { name: "index", computed:{ count(){ return this.$store.state.count; } } } </script>
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,群內有大量PDF可供自取,更有乾貨實戰專案視訊進群免費領取。
結果如下:

我們可以通過元件的計算屬性來儲存state裡面的值,那麼問題來了,如果store太多的話,我們元件裡面的計算屬性豈不是成了這個樣子:
computed:{ count(){ return this.$store.state.count; }, stateA(){ return this.$store.state.stateA; }, stateB(){ return this.$store.state.stateB; } }
這樣獲取共享狀態的資料也沒有什麼問題不過看起來還是有大量的重複冗餘程式碼,我們可以使用 mapState
輔助函式幫助我們生成計算屬性,讓你少按幾次鍵:
當對映的計算屬性的名稱與 state 的子節點名稱相同時,我們也可以給 mapState
傳一個字串陣列。
import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), } }
小結:使用 Vuex 並不意味著你需要將所有的狀態放入 Vuex。雖然將所有的狀態放到 Vuex 會使狀態變化更顯式和易除錯,但也會使程式碼變得冗長和不直觀。如果有些狀態嚴格屬於單個元件,最好還是作為元件的區域性狀態。
3.2.getter
有的時候我們需要對共享狀態裡面的某一個屬性做一些處理後再使用,我們可以把資料獲取後再在元件的計算屬性中處理,舉個例子如下:
// store/index.js state: { count:0, numbers:[0,1,2,3,4,5,6,7,8] }, // Index元件 <template> <div class="index"> {{count}} <br> {{numbers.join()}} </div> </template> <script> import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), numbers(){ return this.$store.state.numbers.filter((item)=>{ return item>3; }) } } } </script>
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,群內有大量PDF可供自取,更有乾貨實戰專案視訊進群免費領取。
結果如下:

那麼問題來了,如果多個元件都要做同樣的處理,我們就需要把一份程式碼複製到多個地方,顯然是不大合理的,於是有了getter,可以理解為元件裡面的計算屬性。示例如下:
/ store/index.js getters: { filterNumbers(state){ return state.numbers.filter((item)=>{ return item>3; }) } }, // Index元件 <template> <div class="index"> {{count}} <br> {{filterNumbers.join()}} </div> </template> <script> import {mapState} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']), filterNumbers(){ return this.$store.getters.filterNumbers; } } } </script>
結果完全一樣,我們可以根據this.$store.getters.屬性名來獲取getters,也可以通過 mapGetters 輔助函式將 store 中的 getter 對映到區域性計算屬性:
具體實現方式如下:
<template> <div class="index"> {{count}} <br> {{filterNumbers.join()}} <br> {{antherNumbers.join()}} </div> </template> <script> import {mapState,mapGetters} from 'vuex' export default { name: "index", computed:{ ...mapState(['count']),6 ...mapGetters(['filterNumbers']), ...mapGetters({ antherNumbers:'filterNumbers' }) } } </script>
如果用同一名字直接把陣列作為引數,如果想改一個名字,可以傳入一個物件作為引數,結果如下:

3.3.mutation
在元件內,來自store的資料只能讀取,不能手動改變,改變store中資料唯一的途徑就是顯示的提交mutations。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個引數。改變程式碼如下:
// store/index.js mutations: { add(state){ state.count++; } }, // Index元件 ** <button @click="add">+</button> ** methods:{ add(){ this.$store.commit('add'); console.log(this.count); } **

連續點選5次增加按鈕,發現count的值也改變了。當然,我們也可以傳參進去
// store/index.js mutations: { add(state,n){ state.count+=n; } }, // Index元件 ** <button @click="add">+</button> ** methods:{ add(){ this.$store.commit('add',10); console.log(this.count); } **
觸發方法語句為:this.$store.commit(方法名);也可以使用輔助函式mapMutations代替:
methods:{ ...mapMutations(['add']), }
3.4.action
前面我們講過,mutation有必須同步執行這個限制,我們在業務需求中有時候需要在獲取ajax請求資料之後再操作或定時器操作資料,這些都屬於非同步請求,要用actions來實現。具體實現如下:
// store/index.js mutations: { changeCount(state){ state.count=3000; }, }, actions: { changeCount3000s(context){ setTimeout(()=>{ context.commit('changeCount') },3000) // Index元件 <button @click="changeCount3000s">點選按鈕3s後count的值改變</button> methods:{ ...mapMutations(['add']), changeCount3000s(){ this.$store.dispatch('changeCount3000s'); } }
前端全棧學習交流圈:866109386,面向1-3經驗年前端開發人員,幫助突破技術瓶頸,提升思維能力,群內有大量PDF可供自取,更有乾貨實戰專案視訊進群免費領取。
我們在點選按鈕3s後count的值改變為3000,我們可以通過this.$store.dispatch(方法名)來觸發事件,也可以通過輔助函式mapActions來觸發。
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex' methods:{ ...mapMutations(['add']), ...mapActions(['changeCount3000s']) }
學會以上幾個屬性的使用基本就可以滿足平時業務中的需求了,但使用Vuex會有一定的門檻和複雜性,它的主要使用場景是大型單頁面應用,如果你的專案不是很複雜,用一個bus也可以實現資料的共享,但是它在資料管理,維護,還只是一個簡單的元件,而Vuex可以更優雅高效地完成狀態管理,所以,是否使用Vuex取決於你的團隊和技術儲備。