Vuex狀態管理(上)
文章目錄
一.概念
vue官方提供的狀態管理器.用於處理全局的數據共享問題的.
狀態:即數據、視圖。狀態管理的本質,就是對應用程序的數據進行科學地流程化管理,目標是讓數據變化可預期、可控。Flux一種數據管理架構方案,這是一種數據管理的思想,最早誕生於React團隊。
- React技術棧中,最出名的狀態管理工具是 Redux和Mobx。
- Vue技術棧中,最出名的狀態管理工具是Vuex。
Vuex只是一種數據管理方案,並不是Vue開發必須的。換句話說,在架構Vue項目時可以不使用Vuex。
雖然可以不使用Vuex,但不得不說Vuex非常強大,所以還是建議儘量用上它。Vuex常用於實現組件之間的數據交互、程序數據緩存等需求。Vuex配合devtools,可以非常方便地調試應用程序中的數據bug。
之前我們學習Vue的時候,各種組件之間傳值,比如props傳值,狀態提升傳值,事件總線,還有通過emit事件回傳等等.那我們這裏引入的Vuex,就是組件之間數據交互的終極解決方案.
二.Vuex的倉庫的五大核心概念
1.state
state是Vuex的數據存儲中心
放在state中的數據,所有組件都可以共享,並且保持同步,只要state中的數據發生變化,視圖中自動更新頁面狀態.
2.getters
getters可以理解爲組件中的計算屬性
放在getters關聯的state,只要發生變化,getters 會自動更新
3.mutations
唯一能夠修改state數據的東西,不允許寫異步代碼
mutation直接同步的修改state的主要入口!在組件中使用this.$store.commit(‘已定義的mutaation方法’,‘負載’)來觸發mutation方法
4.actions
間接的異步修改state,在actions裏面的方法都是異步,比如調接口,定時器等.
實際上在actions中可以直接修改state,但是這樣做在devtools沒有修改的記錄,非常不方便於調試
vuex官方建議:只用mutations來修改state,不要使用actions來修改state
5.module
倉庫模塊的拆分
三.安裝與使用
1.安裝
npm install vuex -S
2.使用
在src目錄中新建一個名爲store.js的文件,然後引入vue,vuex,並註冊vue.use(vuex)
//引入vue
import Vue from 'vue';
//import Vuex
import Vuex from 'vuex';
//註冊Vue.use();
Vue.use(Vuex);
const store = new Vuex.Store({
//Vuex的數據存儲中心
state:{
},
//組件中的計算屬性
getters:{
},
//唯一能夠修改state數據的東西,不允許寫異步代碼
mutations:{
},
//間接的異步修改state,在actions裏面的方法都是異步,比如調接口,定時器等.
actions:{
},
//倉庫模塊的拆分
modules:{
}
});
export default store;
3.main.js引入並掛載
//引入store
import store from './store';
new Vue({
router,
store,//掛載store.js
render: h => h(App),
}).$mount('#app')
4.驗證是否安裝成功
console.log(this.$store);
在任何地方,輸出this.$store即可,比如App.vue的鉤子函數mounted
5.組件中如何使用state和getters
1.方法一
使用掛載到Vue原型上的store對象就是new Vuex.Store()生成的倉庫實例對象
console.log(this.$store.state.xxxxxx);
console.log(this.$store.getters.yyyyy);
2.方法二(推薦) computed
使用computed,計算屬性,實際上就是將方案一中獲取到的數據給計算屬性
computed: {
xxxxxx: function() {
return this.$store.state.xxxxxx;
},
yyyy: function() {
return this.$store.getters.yyyyy;
}
},
3. 方法三(推薦) vuex 輔助函數
就是方案二中的一種優雅寫法,可以認爲是語法糖
組件中從vuex中引入你需要的輔助函數
調用輔助函數,並將其返回的值賦給組件的computed選項
import { mapState, mapGetters } from "vuex";
export default {
computed: {
...mapState(["xxxx", "yyyyy"]),
...mapGetters(["culecount"]),
}
}
mapState的語法和mapGetters語法
// mapState 接收一個數組做爲參數,參數中的每一項,就是在倉庫中的 state 數據
mapState([state1, state2, state3])
// mapGetters 接收一個數組做爲參數,參數中的每一項,就是在倉庫中的 getter 數據
mapGetters([getter1, getter2])
使用計算屬性和輔助函數取值時的區別?
二者效果一樣,但是在VueDevtools中的表現不一樣
使用計算屬性時,插件中顯示的是computed
使用輔助函數時,插件中顯示的是vuexbindings
雖然效果一樣,但是我們一般推薦使用輔助函數的形式!!!
computed: {
//推薦使用展開運算符
...mapState(["count", "msg"]),
...mapGetters(["culecount"]),
xxxxxx: function() {
return this.$store.state.count;
},
yyyy: function() {
return this.$store.getters.culecount;
}
},
6.組件中如何修改state與getters的數據
首先要明確一點:state可以修改,getters是不能被修改的
步驟:
- 倉庫中要提供對應 state修改的mutation函數
- 在組件中去調用mutation
調用mutationd 的2種方式:
1.方法一
直接使用vuex綁定到vue原型上的$store對象的commit()方法
this.$store.commit()
//在倉庫中的 mutations中定義方法
mutations: {
//在mutation中定義一個改變state裏參數的方法
updateCount(state, payload) {
state.count += payload.count;
}
}
//在相應的組件中觸發這個函數
methods: {
clickhandle() {
// 不建議直接改vuex裏的state,雖然可以改,但是不建議
//this.$store.state.count++;
let payload = {
count: 10
};
// 向store提交一個名叫updateCount的mutation方法,申請同步改變count
this.$store.commit("updateCount", payload);
},
}
2.方法二(推薦) vuex 輔助函數
使用vuex的輔助函數,mapMutations和
//在倉庫中的 mutations中定義方法
mutations: {
updateCount(state, payload) {
state.count += payload.count;
},
updateMsg(state,payload){
state.msg=payload;
}
},
//類似解構賦值
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
//在組件中使用vuex輔助函數
methods: {
//推薦使用展開運算符
...mapMutations(["updateCount", "updateMsg"]),
...mapActions(["asyncUpdateCount", "asyncUpdateMsg"]),
//因展開運算符展開的方法,無法傳參,所以這裏可以使用一個函數做中轉
update() {
let payload = {
count: 10
};
this.updateCount(payload);
},
所有的mutation執行,都能在VueDevtools看到
爲何vuex中的state必須使用mutation來修改呢?
- 爲了以一種可以預見的方式去修改數據,不至於讓數據難以理解,雖然可以通過$store對象直接修改,但是在嚴格模式下會報錯,並且VueDevtools無法跟蹤到數據,不方便調試
- 爲了實現調試插件(VueDevtools)的時間旅行機制
7.使用actions異步修改state數據
首先要知道,mutation裏面只允許同步的去修改state數據,
其實mutation中可以異步的去修改state數據,不會報錯,但是會導致調試插件的時間旅行等機制沒有效果
處理異步修改state數據有兩種方式
-
1.不涉及action,直接在組件上的methods方法中寫異步代碼,然後再調用mutation
-
2.涉及action
使用action,首先需要在actions選項中定義action函數
注意:action中不能直接去修改state,要修改state,必須使用當前上下文對象的commit()去執行某個mutation來修改
使用涉及action修改數據的方式也有兩種
1.方法一
在倉庫中的action中通過commit調用mutation中的方法,然後異步處理,然後在需要調用的組件內部methods選項中,通過 this.$store.dispatch()來派發
// actions:間接地異步地修改state
// 在actions裏面的方法,都是異步,比如調接口、定時器等
// 在actions中可以直接state,但這樣做在devtools沒有修改的記錄,非常不便於調試
// Vuex官方特別建議,只用mutations來修改state,不要使用actions來修改state
actions: {
asyncUpdateCount(store, payload) {
setTimeout(() => {
store.commit('updateCount', payload)
}, 2000);
}
}
//組件中
methods: {
clickAsyncHandle() {
let payload = {
count: 10
};
// 向store提交一個名叫asyncUpdateCount的actions方法,申請異步改變count
this.$store.dispatch("asyncUpdateCount", payload);
}
}
2.方法二
使用Vuex中的輔助函數 mapActions
//類似解構賦值
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
methods: {
...mapMutations(["updateCount", "updateMsg"]),
...mapActions(["asyncUpdateCount", "asyncUpdateMsg"]),
}
使用方式與上面mutation的方法基本一致!