vuex是什么锯玛?
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式瓜浸。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài)汇歹,并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化椅棺。也是一種組件間通信的方式犁罩。
上面的例子只是一個(gè)簡(jiǎn)單的組件間通信的例子,在實(shí)際項(xiàng)目中两疚,組件間的通信往往比這要復(fù)雜的很多床估,所以說當(dāng)我們的應(yīng)用遇到多個(gè)組件共享狀態(tài)時(shí),單向數(shù)據(jù)流的簡(jiǎn)潔性很容易被破壞
而vuex就是將所有狀態(tài)集中管理起來诱渤,更加方便的實(shí)現(xiàn)組件間的通信丐巫,以往要實(shí)現(xiàn)數(shù)據(jù)的傳遞需要一步一步的向上傳遞,有了vuex源哩,所有組件都可以向vuex中存數(shù)據(jù)鞋吉,也可以取數(shù)據(jù)
應(yīng)用vuex的好處
- 能夠集中管理共享的數(shù)據(jù),易于開發(fā)和后期的維護(hù)
- 高效的實(shí)現(xiàn)組件之間的數(shù)據(jù)共享励烦,提高開發(fā)效率
- 存在vuex的數(shù)據(jù)也是響應(yīng)式的谓着,能夠?qū)崟r(shí)保持?jǐn)?shù)據(jù)與頁面的同步
應(yīng)用場(chǎng)景
多個(gè)組件共享數(shù)據(jù)或者是跨組件傳遞數(shù)據(jù)時(shí)
vuex基本使用
- 安裝
npm i vuex
- 導(dǎo)入vuex
import Vuex from 'vuex'
Vue.use(Vuex)
- 創(chuàng)建store對(duì)象
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實(shí)例上的store對(duì)象
2.mapState輔助函數(shù),當(dāng)需要訪問的狀態(tài)有多個(gè)時(shí)屉栓,上面的方式就略顯麻煩舷蒲,代碼冗余,vuex提供了mapState函數(shù)解決這個(gè)問題this.$store.state.count
在組件中先從vuex中導(dǎo)入mapState函數(shù)
通過mapstate函數(shù)友多,和展開運(yùn)算符將當(dāng)前組件所需要的全局?jǐn)?shù)據(jù)映射成當(dāng)前組件的computed計(jì)算屬性,函數(shù)傳遞一個(gè)數(shù)組牲平,這種最常用,你想要什么數(shù)據(jù)域滥,就傳入該數(shù)據(jù)的名稱纵柿,這個(gè)名稱也將作為該組件的一個(gè)計(jì)算屬性使用import {mapState} from "vuex"
computed: { ...mapState(['count']) } // 使用展開運(yùn)算符在這里必須用{}包起來 // 如果當(dāng)前組件沒有私有的計(jì)算屬性,可以直接簡(jiǎn)寫成 computed: mapState(['count'])
另一種方法就是傳入配置對(duì)象
// 如果當(dāng)前組件沒有私有的計(jì)算屬性启绰,可以直接簡(jiǎn)寫成 computed: mapState({}) // 有私有的計(jì)算屬性,不能簡(jiǎn)寫 computed: { ...mapState({ // 函數(shù)方法有一個(gè)參數(shù)state昂儒,就是數(shù)據(jù)源 aaa(名字自定義): state => state.count // 簡(jiǎn)寫 aaa: 'count' // 傳字符串的方式等同于state => state.count // 若要訪問組件的this,就得寫成普通函數(shù) aaa(state){ // 必須return return this.num + state.count } }) }
二委可、mutations
vuex不允許在組件中修改state中的狀態(tài)渊跋,如果想要修改state的數(shù)據(jù),唯一的方法就是通過mutations修改,其實(shí)在組件中是可以直接修改的拾酝,但是這樣通過mutations修改的方式燕少,可以更加集中的監(jiān)控所有數(shù)據(jù)的變化。
在mutations中定義一些修改state數(shù)據(jù)的方法微宝,方法第一個(gè)參數(shù)就是state對(duì)象
mutations: {
add(state){
state.count ++
}
}
(1)觸發(fā)mutation的方法
- 通過store對(duì)象
this.$store.commit('add')
- mapMutations映射
組件中導(dǎo)入mapMutations函數(shù)
import {mapMutations} from 'vuex'
這次是在組件的methods中棺亭,將mutation映射成methods的方法
methods: {
...mapMustations(['add'])
}
(2)mutation傳值(官網(wǎng)將傳遞的值稱為載荷)
對(duì)于mutaion而言,方法接受的第一個(gè)參數(shù)始終是自身的state蟋软,第二個(gè)才是傳遞過來的參數(shù)镶摘,這個(gè)參數(shù)一般是一個(gè)對(duì)象,因?yàn)閷?duì)象可以攜帶更多的數(shù)據(jù)岳守。當(dāng)然只有一條數(shù)據(jù)可以只傳遞這條數(shù)據(jù)
mutations: {
add(state, param){
state.count += param.xxx
}
}
還可以寫成一種對(duì)象的方式
this.$store.commit({
type: add,
step: 20
});
// mutation的寫法不變
mapMutations傳值
(3)注意
- 一般我們會(huì)將mutation的名字寫成是全大寫和“_”,如
mutations: {
SET_TOKEN(state){},
RECEIVE_CATE_LIST(state){}.
...
}
- 方法中不能執(zhí)行異步操作凄敢,也不能執(zhí)行if語句
Vuex中所有的狀態(tài)更新的唯一途徑都是mutation,異步操作通過 Action 來提交 mutation實(shí)現(xiàn)湿痢,這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化涝缝,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用。
每個(gè)mutation執(zhí)行完成后都會(huì)對(duì)應(yīng)到一個(gè)新的狀態(tài)變更譬重,這樣devtools就可以打個(gè)快照存下來拒逮,然后就可以實(shí)現(xiàn) time-travel 了。如果mutation支持異步操作臀规,就沒有辦法知道狀態(tài)是何時(shí)更新的滩援,無法很好的進(jìn)行狀態(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中的每一個(gè)方法的第一個(gè)參數(shù)默認(rèn)使context鸯屿,是與 store 實(shí)例具有相同方法和屬性的對(duì)象(context !== store對(duì)象)俩檬。而在組件中執(zhí)行actions方法的方式就是:this.$store.dispatch('方法名')
比如定義一個(gè)定時(shí)器異步的使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中的一個(gè)方法 }
methods: { // 若要自定義方法名 ...mapActions({ newMethodName(){ this.$store.dispatch("asyncIncrement"); } //或者 newMethodName: "asyncIncrement" }) }
-
傳遞載荷(參數(shù))
1.dispatchthis.$store.dispatch('xxx', params) // 對(duì)象形式 this.$store.dispatch({ type: asyncIncrement, params })
2.mapActions
四、getters
有時(shí)候我們需要從 store 中的 state 中派生出一些狀態(tài)技竟,例如對(duì)列表進(jìn)行過濾等冰肴,其實(shí)也可以理解為是類似vue的計(jì)算屬性,函數(shù)接受一個(gè)參數(shù)state,也就是數(shù)據(jù)源,數(shù)據(jù)也是響應(yīng)式的熙尉,state數(shù)據(jù)變化联逻。getters里面的數(shù)據(jù)也會(huì)隨之變化,不會(huì)修改state中的數(shù)據(jù),第二個(gè)參數(shù)是getters检痰,通過這個(gè)屬性我們就可以訪問到其他的getter了
- 定義getter
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
nameList: [
{
title: "標(biāo)題一",
id: 1
},{
title: "標(biāo)題二",
id: 2
},{
title: "標(biāo)題三",
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中的屬性
其實(shí)和state差不多,就不多說了
- this.$store.getters.getterName
this.$store.getters.numArr
- mapGetters
import { mapGetters } from "vuex";
// 同state一樣铅歼,將getters中的getter映射成組件的computed的計(jì)算屬性
export default {
computed: {
...mapGetters(['numArr'])
// 重命名
...mapGetters({
newName: 'numArr'
})
},
};