Vuex Vuex是專為Vue.js應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。 應用場景 對於深層嵌套組件,依靠props進行父子組件的傳遞顯得太過臃腫,而且難以維護。而vuex的出現就是為瞭解決數據傳遞的問題。Vuex作 ...
Vuex
Vuex是專為Vue.js應用程式開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。
應用場景
對於深層嵌套組件,依靠props進行父子組件的傳遞顯得太過臃腫,而且難以維護。而vuex的出現就是為瞭解決數據傳遞的問題。Vuex作為一個全局管理倉庫,可以管理所有組件的狀態state,不同組件之間也可依靠Vuex來共用狀態State。
Vuex不同於單純的全局對象
1,Vuex的狀態存儲是響應式的。當Vue組件從store中讀取狀態時,若store的中的狀態發生變化,那麼相應的組件也會相應的得到高效更新。
2,改變store中狀態的唯一途徑就是顯式地提交mutation。所有的state的改變都必須經過mutation事件,方便我們跟蹤每一個狀態的的變化。
核心概念
state
負責存儲整個應用的狀態數據。在vue組件中獲取Vuex狀態的方式如下,在計算屬性中返回某個狀態:
1,需要在DOM節點上獲取到狀態;
實現:在項目中,在組件中把存在Vuex中的“columns”取出來,並顯示在該組件上
1),在computed中返回該狀態。
1 computed: { 2 columns(){ 3 return this.$store.state.columns; 4 } 5 },
2),在需要用到的dom節點上進行操作。
1 <el-col :span="20"> 2 <el-checkbox-group v-model="column"> 3 <el-checkbox :label="item.name" v-for="(item,index) in columns" :key="index">{{item.name}}</el-checkbox> 4 </el-checkbox-group> 5 </el-col>
結果:每當store.state.columns變化時,都會重新計算屬性,並且觸發更新相關聯的DOM。
2,在vue生命周期中獲取到Vuex中的狀態,可以直接用this.$store.state對象
eg:
this.id = this.$store.state.articleId;
mapState輔助函數
當一個組件需要獲取多個狀態時,vuex提供了mapState輔助函數生成計算屬性。
實現:從Vuex中獲取“activityLeft”和“columns”兩個狀態時,可以按以下兩個方式獲取。
1),直接獲取
1 computed: { 2 activityLeft(){ 3 return this.$store.state.activityLeft; 4 }, 5 columns(){ 6 return this.$store.state.columns; 7 } 8 }
2),用mapState輔助函數輔助函數獲取
1 computed: { 2 ...mapState([ 3 'activityLeft', 4 'columns' 5 ]) 6 },
mutation
上面說到,更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。
Vuex 中的mutation非常類似於事件:每個 mutation 都有一個字元串的 事件類型 (type) 和 一個 回調函數 (handler)。
實現:在組件中改變Vuex狀態中的acticleId狀態,不可以用“this.$store.state.articleId = 1”這種方式進行修改,需要以下麵的方面進行修改。
eg:
1),組件中需要用state.commit來喚醒mutation中的handler。例如在點擊編輯時,獲取到該item的id傳遞給對應的handler
1 handleCurrentChange(id) { 2 this.$store.commit("getArticleId",id); 3 }
2),在Vuex中添加一一對應的handler
1 mutations:{ 2 getArticleId(state,id){ 3 state.articleId = id; 4 }, 5 }
註意:
1,最好在提前在你的 store 中初始化好所有所需屬性。上述例子應該在state中先初始化好articleId。
2,mutation必須是同步函數。在 mutation 中混合非同步調用會導致你的程式很難調試,如果需要處理非同步操作,可以使用Action
Action
1,Action 提交的是 mutation,而不能直接變更狀態
2,Action 可以包含任意非同步操作
實現:在項目中,在Action中使用axios去獲取數據,並把數據存進Vuex的狀態裡面。
1),在組件的methods中通過 store.dispatch
方法觸發Action
1 handleSizeChange(val) { 2 this.pageSize = val; 3 let data = { 4 "type":this.$store.state.navName, 5 "wid":this.$store.state.websiteId, 6 "pageSize":this.pageSize, 7 "pageNum":this.pageNum, 8 "searchTitle":this.searchTitle 9 }; 10 this.$store.dispatch("getArticle",data); 11 },
2),在Vuex註冊一一對應的Action
1 actions:{ 2 getArticle({commit},{type='',searchTitle='',wid,pageNum=1,pageSize=20}){ 3 axios.post(api.url+'articleList',{ 4 type:type, 5 searchTitle:searchTitle, 6 wid:wid, 7 pageSize:pageSize, 8 pageNum:pageNum 9 }).then((response)=>{ 10 if(response.data.ret == 0){ 11 var data = response.data; 12 var msg = data.msg; 13 var total = data.total; 14 commit('getArticle',{msg,total}) 15 } 16 }); 17 }, 18 }
3),通過提交 mutation 來記錄狀態變更
1 mutations:{ 2 getArticle(state,data){ 3 var res = data.msg; 4 state.activityList = res; 5 state.total = data.total; 6 }, 7 }
重點:store.dispatch
可以處理被觸發的 action 的處理函數返回的 Promise,並且 store.dispatch
仍舊返回 Promise:
eg:一個 store.dispatch
在不同模塊中可以觸發多個 action 函數。
1 actions: { 2 async actionA ({ commit }) { 3 commit('gotData', await getData()) 4 }, 5 async actionB ({ dispatch, commit }) { 6 await dispatch('actionA') // 等待 actionA 完成 7 commit('gotOtherData', await getOtherData()) 8 } 9 }
以上就是我在項目中基於vue-cli框架中使用Vuex的一些例子。最後上面提到的vuex狀態附在下列store.js中。
1 import Vue from 'vue'; 2 import Vuex from 'vuex'; 3 import axios from 'axios'; 4 import api from '../api/api.js'; 5 Vue.use(Vuex); 6 let store = new Vuex.Store({ 7 state:{ 8 columns:[], 9 articleId:'', 10 }, 11 mutations:{ 12 getArticle(state,data){ 13 var res = data.msg; 14 state.activityList = res; 15 state.total = data.total; 16 }, 17 getArticleId(state,id){ 18 state.articleId = id; 19 }, 20 }, 21 actions:{ 22 getArticle({commit},{type='',searchTitle='',wid,pageNum=1,pageSize=20}){ 23 axios.post(api.url+'articleList',{ 24 type:type, 25 searchTitle:searchTitle, 26 wid:wid, 27 pageSize:pageSize, 28 pageNum:pageNum 29 }).then((response)=>{ 30 if(response.data.ret == 0){ 31 var data = response.data; 32 var msg = data.msg; 33 var total = data.total; 34 commit('getArticle',{msg,total}) 35 } 36 }); 37 }, 38 } 39 }); 40 export default store;