vuex是什么?
Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲管理應用的所有組件的狀態(tài),并以相應的規(guī)則保證狀態(tài)以一種可預測的方式發(fā)生變化。也是一種組件間通信的方式。

上面的例子只是一個簡單的組件間通信的例子,在實際項目中,組件間的通信往往比這要復雜的很多,所以說當我們的應用遇到多個組件共享狀態(tài)時,單向數(shù)據(jù)流的簡潔性很容易被破壞
而vuex就是將所有狀態(tài)集中管理起來,更加方便的實現(xiàn)組件間的通信,以往要實現(xiàn)數(shù)據(jù)的傳遞需要一步一步的向上傳遞,有了vuex,所有組件都可以向vuex中存數(shù)據(jù),也可以取數(shù)據(jù)

應用vuex的好處
- 能夠集中管理共享的數(shù)據(jù),易于開發(fā)和后期的維護
- 高效的實現(xiàn)組件之間的數(shù)據(jù)共享,提高開發(fā)效率
- 存在vuex的數(shù)據(jù)也是響應式的,能夠?qū)崟r保持數(shù)據(jù)與頁面的同步
應用場景
多個組件共享數(shù)據(jù)或者是跨組件傳遞數(shù)據(jù)時
vuex基本使用
- 安裝
npm i vuex
- 導入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
- 創(chuàng)建store對象
const store = new Vuex.Store({
state: {
// 存放全局共享的數(shù)據(jù)
},
actions: {},
mutatiions: {},
getters: {}
})
- 全局掛載store到vue上
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
然后在組件中就可以通過this.$store訪問到vuex了
vuex核心概念
一、state
state作為唯一的數(shù)據(jù)源,所有的共享數(shù)據(jù)都存放在state中,如:
const store = new Vuex.Store({
state: {
count: 0
}
})
- 組件訪問state數(shù)據(jù)的方式
- 通過已經(jīng)掛載到vue實例上的store對象
2.mapState輔助函數(shù),當需要訪問的狀態(tài)有多個時,上面的方式就略顯麻煩,代碼冗余,vuex提供了mapState函數(shù)解決這個問題this.$store.state.count
在組件中先從vuex中導入mapState函數(shù)
通過mapstate函數(shù),和展開運算符將當前組件所需要的全局數(shù)據(jù)映射成當前組件的computed計算屬性,函數(shù)傳遞一個數(shù)組,這種最常用,你想要什么數(shù)據(jù),就傳入該數(shù)據(jù)的名稱,這個名稱也將作為該組件的一個計算屬性使用import {mapState} from "vuex"computed: { ...mapState(['count']) } // 使用展開運算符在這里必須用{}包起來 // 如果當前組件沒有私有的計算屬性,可以直接簡寫成 computed: mapState(['count'])Snipaste_2021-08-10_11-38-20.png
另一種方法就是傳入配置對象
// 如果當前組件沒有私有的計算屬性,可以直接簡寫成 computed: mapState({}) // 有私有的計算屬性,不能簡寫 computed: { ...mapState({ // 函數(shù)方法有一個參數(shù)state,就是數(shù)據(jù)源 aaa(名字自定義): state => state.count // 簡寫 aaa: 'count' // 傳字符串的方式等同于state => state.count // 若要訪問組件的this,就得寫成普通函數(shù) aaa(state){ // 必須return return this.num + state.count } }) }
二、mutations
vuex不允許在組件中修改state中的狀態(tài),如果想要修改state的數(shù)據(jù),唯一的方法就是通過mutations修改,其實在組件中是可以直接修改的,但是這樣通過mutations修改的方式,可以更加集中的監(jiān)控所有數(shù)據(jù)的變化。
在mutations中定義一些修改state數(shù)據(jù)的方法,方法第一個參數(shù)就是state對象
mutations: {
add(state){
state.count ++
}
}
(1)觸發(fā)mutation的方法
- 通過store對象
this.$store.commit('add')


- mapMutations映射
組件中導入mapMutations函數(shù)
import {mapMutations} from 'vuex'
這次是在組件的methods中,將mutation映射成methods的方法
methods: {
...mapMustations(['add'])
}

(2)mutation傳值(官網(wǎng)將傳遞的值稱為載荷)
對于mutaion而言,方法接受的第一個參數(shù)始終是自身的state,第二個才是傳遞過來的參數(shù),這個參數(shù)一般是一個對象,因為對象可以攜帶更多的數(shù)據(jù)。當然只有一條數(shù)據(jù)可以只傳遞這條數(shù)據(jù)
mutations: {
add(state, param){
state.count += param.xxx
}
}

還可以寫成一種對象的方式
this.$store.commit({
type: add,
step: 20
});
// mutation的寫法不變
mapMutations傳值

(3)注意
- 一般我們會將mutation的名字寫成是全大寫和“_”,如
mutations: {
SET_TOKEN(state){},
RECEIVE_CATE_LIST(state){}.
...
}
- 方法中不能執(zhí)行異步操作,也不能執(zhí)行if語句
Vuex中所有的狀態(tài)更新的唯一途徑都是mutation,異步操作通過 Action 來提交 mutation實現(xiàn),這樣使得我們可以方便地跟蹤每一個狀態(tài)的變化,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應用。
每個mutation執(zhí)行完成后都會對應到一個新的狀態(tài)變更,這樣devtools就可以打個快照存下來,然后就可以實現(xiàn) time-travel 了。如果mutation支持異步操作,就沒有辦法知道狀態(tài)是何時更新的,無法很好的進行狀態(tài)的追蹤,給調(diào)試帶來困難。
引自「水墨-青花」:https://blog.csdn.net/lovemyself196221/article/details/105488288
- 大多數(shù)情況下也不是在組件中觸發(fā),而是通過actions中的方法觸發(fā)mutation
三、actions
actions和mutations類似,不同的是,actions是提交mutation修改共享數(shù)據(jù),不是直接改變共享數(shù)據(jù)的,只有通過mutation才能修改state中的函數(shù);actions中可以執(zhí)行異步操作。actions中的每一個方法的第一個參數(shù)默認使context,是與 store 實例具有相同方法和屬性的對象(context !== store對象)。而在組件中執(zhí)行actions方法的方式就是:this.$store.dispatch('方法名')
比如定義一個定時器異步的使count自增
actions: {
async asyncIncrement(context){
console.log(context)
}
}

而提交mutation的方法是commit,利用解構(gòu)賦值將commit結(jié)構(gòu)出來,提交mutation修改state的值

-
分發(fā)actions
說白了就是觸發(fā)actions中的方法- this.$store.dispatch("xxx")
2.mapActions,映射在組件的methods中
methods: { ...mapActions(['asyncIncrement']) // 將asyncIncrement映射成methods中的一個方法 }methods: { // 若要自定義方法名 ...mapActions({ newMethodName(){ this.$store.dispatch("asyncIncrement"); } //或者 newMethodName: "asyncIncrement" }) } -
傳遞載荷(參數(shù))
1.dispatchthis.$store.dispatch('xxx', params) // 對象形式 this.$store.dispatch({ type: asyncIncrement, params })Snipaste_2021-08-10_19-47-17.png
2.mapActions
Snipaste_2021-08-10_19-49-43.png
四、getters
有時候我們需要從 store 中的 state 中派生出一些狀態(tài),例如對列表進行過濾等,其實也可以理解為是類似vue的計算屬性,函數(shù)接受一個參數(shù)state,也就是數(shù)據(jù)源,數(shù)據(jù)也是響應式的,state數(shù)據(jù)變化。getters里面的數(shù)據(jù)也會隨之變化,不會修改state中的數(shù)據(jù),第二個參數(shù)是getters,通過這個屬性我們就可以訪問到其他的getter了
- 定義getter
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
nameList: [
{
title: "標題一",
id: 1
},{
title: "標題二",
id: 2
},{
title: "標題三",
id: 3
}
]
},
getters: {
numArr: (state, getters) => {
console.log(getters.testGetters) // {a: 2}
return state.nameList.filter((item) => {
return item.num > 11
})
},
testGetters: () {
return {a: 2}
}
}
})
組件中訪問getters中的屬性
其實和state差不多,就不多說了
- this.$store.getters.getterName
this.$store.getters.numArr
- mapGetters
import { mapGetters } from "vuex";
// 同state一樣,將getters中的getter映射成組件的computed的計算屬性
export default {
computed: {
...mapGetters(['numArr'])
// 重命名
...mapGetters({
newName: 'numArr'
})
},
};


