Vue使用Vuex一步步封裝并使用store全過程
一、安裝Vuex依賴
cnpm install vuex --save
二、一步步封裝store
1. main.js中全局引入store倉庫(下一步創(chuàng)建)
import store from './store' //引入store
new Vue({
el: '#app',
router,
store, //掛載store,this將自動生成$store屬性
template: '<App/>',
components: { App }
})
掛載store,this將自動生成$store屬性
2. this.$store
創(chuàng)建store倉庫:習(xí)慣在src下創(chuàng)建store文件夾,再創(chuàng)建index.js,內(nèi)容:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store(); export default store;
此時你已經(jīng)有了一個空的store全局倉庫,沒有任何功能,但可以在任何vue實例下使用 this.$store 去訪問它。
- store使用范圍均是可以全局使用;
- let a=1; {a:a}.a 的縮寫是 {a}.a,即當(dāng)字典的鍵和值命名一樣時,可以省略只寫a
- state、getters、mutations、mutations均是Vuex封裝好的特殊變量,以下聲明的功能變量均是這些名字,一個好處是store掛載該功能時可以簡寫(如3-1,本例均如此)。當(dāng)然你也可直接在store中寫功能(如3-2)。
3. this.$store.state
給store倉庫讀取數(shù)據(jù)功能:state
/********* 3-1 **********/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
};
const store = new Vuex.Store({
state
});
export default store;
此時你的store倉庫已經(jīng)有了存取數(shù)據(jù)的功能,可以用 this.$store.state.themeColor 等數(shù)據(jù)了。
下面是第二種寫法
/********* 3-2 **********/
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
//要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
}
});
export default store;
4. this.$store.getters(this. $store.state的升級)
給state功能升級,讓他擁有計算能力(類似vue中的computed方法):getters:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
};
const getters = { //實時監(jiān)聽state值的變化(最新狀態(tài))
getThemeColor(state) { //定義函數(shù),返回處理過的val,命名最好有代表性
let hour = new Date().getHours();
// 如果白天則主題色不透明,反之
state.themeColor.opacity = 8 <= hour && hour <= 20;
return state.themeColor
}
};
const store = new Vuex.Store({
state, // 掛載存取數(shù)據(jù)功能
getters //掛載數(shù)據(jù)計算功能
});
export default store;
此時使用 this.$store.getters.getThemeColor 獲取顏色,將自動根據(jù)時間的不同自動設(shè)置主題是否有透明的效果
5. this.$store.commit(‘mutations’)
給store倉庫使用函數(shù)功能(只為操作state數(shù)據(jù)):mutations - 同步
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
};
const getters = { //實時監(jiān)聽state值的變化(最新狀態(tài))
getThemeColor(state) { //定義函數(shù),返回處理過的val,命名最好有代表性
let hour = new Date().getHours();
// 如果白天則主題色不透明,反之
state.themeColor.opacity = 8 <= hour && hour <= 20;
return state.themeColor
}
};
const mutations = {
//自定義改變state初始值的方法,這里面的參數(shù)除了state之外還可以再傳額外的參數(shù)(變量或?qū)ο?;
clearCatch(state) {
state.cache = "";
state.changeThemeCount= 0;
},
setThemeColor(state,color,opacity){
state.themeColor.val = color;
state.themeColor.opacity = opacity;
state.changeThemeCount++;
}
};
const store = new Vuex.Store({
state, // 掛載存取數(shù)據(jù)功能
getters, //掛載數(shù)據(jù)計算功能
mutations // 掛載函數(shù)功能
});
export default store;
此時可以使用 this.$store.commit(‘setThemeColor’,‘grey’,‘1’) 了(注意第一個參數(shù)是函數(shù)名,不是傳參給state的,state自己會傳,后兩個才是對應(yīng)傳參)。
可以主動設(shè)置主題色和透明度,操作是同步的,即如果你在同一個組件連續(xù)調(diào)用多次setThemeColor函數(shù),獲取倉庫中state.changeThemeCount的值是一樣的,下面介紹異步函數(shù)。
6. this.$store.dispatch(‘actions’)(this. $store.commit(‘mutations’)的升級)
給store倉庫的函數(shù)commit功能升級(只為異步操作mutations中的函數(shù)):actions - 異步
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
};
const getters = { //實時監(jiān)聽state值的變化(最新狀態(tài))
getThemeColor(state) { //定義函數(shù),返回處理過的val,命名最好有代表性
let hour = new Date().getHours();
// 如果白天則主題色不透明,反之
state.themeColor.opacity = 8 <= hour && hour <= 20;
return state.themeColor
}
};
const mutations = {
//自定義改變state初始值的方法,這里面的參數(shù)除了state之外還可以再傳額外的參數(shù)(變量或?qū)ο?;
clearCatch(state) {
state.cache = "";
state.changeThemeCount= 0;
},
setThemeColor(state,color,opacity){
state.themeColor.val = color;
state.themeColor.opacity = opacity;
state.changeThemeCount++;
}
};
const actions = {
//自定義觸發(fā)mutations里函數(shù)的方法,context與store 實例具有相同方法和屬性
setThemeColorAction(context,color,opacity){
context.commit('setThemeColor',color,opacity);
}
};
const store = new Vuex.Store({
state, // 掛載存取數(shù)據(jù)功能
getters, //掛載數(shù)據(jù)計算功能
mutations, // 掛載函數(shù)功能
actions, // 掛載異步函數(shù)
});
export default store;
此時可以使用 this.$store.dispatch(‘setThemeColorAction’,‘grey’,‘1’) 了(注意第一個參數(shù)是函數(shù)名,不是傳參給context的,context自己會傳,后兩個才是對應(yīng)傳參)。
可以主動設(shè)置主題色和透明度,操作是異步的,即如果你在同一個組件連續(xù)調(diào)用多次setThemeColorAction函數(shù),獲取倉庫中state.changeThemeCount的值就不是一樣的。
7. strict嚴(yán)格模式
export default new Vuex.Store({
strict: true,
state: {
...
},
...
}
此模式下所有的狀態(tài)變更(即更新state)必須使用mutation(commit),如果在組件中直接修改state則會報錯。這樣的好處是所有的state的更新都體現(xiàn)在倉庫中,整改方便;使用devTools調(diào)試工具時可以跟蹤到狀態(tài)的修改。
三、modules 模塊化
第二個模塊介紹了store倉庫的四個功能:state、getters、mutations和actions,下面介紹第五個功能:modules。
- 當(dāng)項目比較大時,一個store中數(shù)據(jù)會非常多而復(fù)雜,不易管理。此時便可建多個“子倉庫”,分別對應(yīng)不同模塊做數(shù)據(jù)的讀取和操作。
- 注意主倉庫還是那一個,只要把他的“子倉庫”放在主倉庫的modules下即可。
- 子倉庫看著很像倉庫,其實它并不是store的實例,不是倉庫(new Vuex.Store()實例化后的對象才是倉庫),只是一個普通js對象(字典)。
1、在store下新建modules文件夾,在modules下新建home.js“子倉庫”。

即home.js只管主頁下的數(shù)據(jù)(一般不要分的太細(xì),最多一個頁面一個倉庫管簡潔),下面是home.js代碼
//home.js
const state={
users:[] //存訪問該頁面的所有用戶
};
const getters={
getUsers(state){ //獲取訪問該頁面的所有用戶
// 對數(shù)據(jù)清理-除去臟數(shù)據(jù)
if (state.users.includes('*')) delete state.users['*']
return state.users;
}
};
const mutations={
addUser(state,name){ //增加訪問用戶
state.collects.push(name)
}
};
const actions={
invokeAddUser(context,name){ //觸發(fā)mutations里面的addUser,傳入數(shù)據(jù)形參name對應(yīng)到users
context.commit('addUser',name);
}
};
// 注意和倉庫的區(qū)別
const store = {
// namespaced用于在全局引用此文件里的方法時標(biāo)識這一個的文件名,使得讓人明白這些數(shù)據(jù)來自哪個倉庫
// 即當(dāng)你需要在別的文件里面使用子倉庫(mapStates、mapGetters、mapActions)時,里面的方法需要注明來自哪一個模塊的方法
namespaced:true,
state,
getters,
mutations,
actions
}
export default store;
2.“子倉庫”創(chuàng)建完成,要讓主倉庫引用它:
import Vue from 'vue';
import Vuex from 'vuex';
import home from './modules/home.js'
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問的state對象,賦予初始屬性值
themeColor: {val:'blue',opacity:false},
changeThemeCount:0,
cache:''
};
const getters = { //實時監(jiān)聽state值的變化(最新狀態(tài))
getThemeColor(state) { //定義函數(shù),返回處理過的val,命名最好有代表性
let hour = new Date().getHours();
// 如果白天則主題色不透明,反之
state.themeColor.opacity = 8 <= hour && hour <= 20;
return state.themeColor
}
};
const mutations = {
//自定義改變state初始值的方法,這里面的參數(shù)除了state之外還可以再傳額外的參數(shù)(變量或?qū)ο?;
clearCatch(state) {
state.cache = "";
state.changeThemeCount= 0;
},
setThemeColor(state,color,opacity){
state.themeColor.val = color;
state.themeColor.opacity = opacity;
state.changeThemeCount++;
}
};
const actions = {
//自定義觸發(fā)mutations里函數(shù)的方法,context與store 實例具有相同方法和屬性
setThemeColorAction(context,color,opacity){
context.commit('setThemeColor',color,opacity);
}
};
const store = new Vuex.Store({
state, // 掛載存取數(shù)據(jù)功能
getters, //掛載數(shù)據(jù)計算功能
mutations, // 掛載函數(shù)功能
actions, // 掛載異步函數(shù)
modules:{ // 掛載子倉庫
home
}
});
export default store;
此時便有了第一個“子倉庫”了!
四、使用倉庫
1. 無map系列
適合使用場景較少:
建好倉庫,組件中直接使用state、getters、mutations、actions:
this.$store.state.*this.$store.getters.*this.$store.commit.*this.$store.dispatch.*
2. map映射系列
適合使用場景頻繁:
使用mapGetters、mapActions 和 mapStates之前需要import導(dǎo)入:
import {mapState,mapGetters,mapActions} from 'vuex';
使用ES6新語法-超引用,將某個功能下的數(shù)據(jù)或方法全部映射出來以供使用,下面是mapState、mapGetters、mapActions的例子:
//這里的...是超引用,映射內(nèi)容,可以寫在computed下、methods下等(一般放在開頭)
// 直接從庫中取值 - 將庫里的users值返回給字典中的users并映射給this組件
...mapState({
users:state=>state.home.users
}),
// 使用計算屬性 - 將庫里的users計算后的值返回給字典中的users并映射給this組件
...mapGetters('home',{
users:'getUsers' //獲取清理后的數(shù)據(jù)
//由于home倉庫 namespaced:true,所以第一個參數(shù)作為標(biāo)識
// 不使用標(biāo)識訪問的是主倉庫
})
// 使用異步函數(shù) - 以數(shù)組中的函數(shù)名,從庫中對應(yīng)的函數(shù)映射給this組件以供使用
...mapActions('home',['invokeAddUser'])
// 有某個組件 <span @click='invokeAddUser(name)'></span>
// 或者直接使用 this.invokeAddUser(name)
3. 擴展
mapState映射的三種寫法
computed: mapState({
// 箭頭函數(shù)可使代碼更簡練
count: state => state.count,
// 傳字符串參數(shù) 'count' 等同于 `state => state.count`
countAlias: 'count',
// 為了能夠使用 `this` 獲取局部狀態(tài),必須使用常規(guī)函數(shù)
countPlusLocalState (state) {
return state.count + this.localCount
}
})
2、當(dāng)映射的計算屬性的名稱與state的子節(jié)點名稱相同時,
我們也可以給 mapState傳一個字符串?dāng)?shù)組。
computed: mapState([ // 數(shù)組
"count"
])
3、倉庫中action的第二種接收參數(shù)
const actions = {
//自定義觸發(fā)mutations里函數(shù)的方法,{commit}與store 實例具有相同方法和屬性
setThemeColorAction({commit},color,opacity){
commit('setThemeColor',color,opacity);
}
};
3. 總結(jié)
1、Vuex 是一個專門為 Vue.js 應(yīng)用所設(shè)計的集中式狀態(tài)管理架構(gòu)。它借鑒了 Flux 和 Redux 的設(shè)計思想,但簡化了概念,并且采用了一種為能更好發(fā)揮 Vue.js 數(shù)據(jù)響應(yīng)機制而專門設(shè)計的實現(xiàn)。
2、Vuex 的四個核心概念分別是:
The state tree:Vuex 使用單一狀態(tài)樹,用一個對象就包含了全部的應(yīng)用層級狀態(tài)。至此它便作為一個『唯一數(shù)據(jù)源(SSOT)』而存在。這也意味著,每個應(yīng)用將僅僅包含一個 store 實例。單狀態(tài)樹讓我們能夠直接地定位任一特定的狀態(tài)片段,在調(diào)試的過程中也能輕易地取得整個當(dāng)前應(yīng)用狀態(tài)的快照。Getters: 用來從 store 獲取 Vue 組件數(shù)據(jù)。Mutators: 事件處理器用來驅(qū)動狀態(tài)的變化。Actions: 可以給組件使用的函數(shù),以此用來驅(qū)動事件處理器 mutations
3、Vuex 應(yīng)用中數(shù)據(jù)的流向(Vuex 官方圖)

數(shù)據(jù)流都是單向的組件能夠調(diào)用 actionaction 用來派發(fā) Mutation只有 mutation 可以改變狀態(tài)store 是響應(yīng)式的,無論 state 什么時候更新,組件都將同步更新
最后
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue3+vite應(yīng)用中添加sass預(yù)處理器問題
這篇文章主要介紹了vue3+vite應(yīng)用中添加sass預(yù)處理器問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02
vue前端開發(fā)輔助函數(shù)狀態(tài)管理詳解示例
vue的應(yīng)用狀態(tài)管理提供了mapState、mapGetters、mapMutations、mapActions四個輔助函數(shù),所謂的輔助函數(shù)分別對State、Getters、Mutations、Actions在完成狀態(tài)的使用進行簡化2021-10-10

