寫在前面vue
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。ios
我爲何使用vuexvuex
當咱們的應用遇到多個組件共享狀態時 Vuex 能夠幫助咱們管理共享狀態axios
本筆記只作參考, 官方學習入口點擊這裏api
不打算開發大型單頁應用,使用 Vuex 多是繁瑣冗餘的。確實是如此——若是您的應用夠簡單,您最好不要使用 Vuex。bash
預熱前奏app
// store.js
import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const state = {} // 數據倉庫
const mutations = {} // 操做方法
const actions = {} // 操做方法命令
const getters = {} // 數據計算
export default new Vuex.Store({
state,
mutations,
actions,
getters
})
複製代碼
這幾個屬性是幹啥玩意兒呢?異步
state
倉庫數據,用於存儲數據async
mutations
操做倉庫數據的方法集合,建議用於對倉庫單個數據的操做模塊化
actions
派發事件 | 可執行的其餘操做 | 可用異步代碼或多個事件派發【簡言之: 生而爲數據的複雜操做】
getters
倉庫數據的計算屬性,形如組件中的 computed 的使用
以上是一個基本的 vuex
倉庫,要想在項目中使用,咱們還須要在 main.js 中引入並掛載
// main.js
import store from "./store.js" // 引入
new Vue({
store, // 掛載
render: h => h(App)
}).$mount("#app");
複製代碼
爲了更加清晰地使用vuex,咱們初步對文件代碼進行分離
# 目錄
|-- store
|-- index.js
|-- state.js
|-- mutations-type.js
|-- mutations.js
|-- actions.js
複製代碼
index.js 使用 vuex 入口
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import * as getters from './getters'
import * as actions from './actions'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
getters,
actions
})
複製代碼
state.js 數據集結地
const state = {
list: [],
tempList: []
}
export default state
複製代碼
mutations-type.js 事件名
export const SET_LIST = 'SET_LIST'
export const SET_TEMP_LIST = 'SET_TEMP_LIST'
複製代碼
mutations.js 管家
import * as types from './mutations-type'
const mutations = {
/************************************* *** 變動state中的某數據狀態 *************************************/
[types.SET_LIST](state, list) {
state.list = list
},
[types.SET_TEMP_LIST](state, list) {
state.tempList = list
}
}
export default mutations
複製代碼
actions.js 帶Buff的管家
import axios from "axios";
import * as types from "./mutations-type";
export const actions = {
/**************************************** *** 可包含任何異步請求 *** 多重命令mutation, 並不是直接變動數據 ****************************************/
async getListAndSet({ commit }, queryParams) {
const ret = await axios.get('api/test/test1', {
params: queryParams
}).then(res => res.data.data)
commit(types.SET_LIST, ret)
commit(types.SET_TEMP_LIST, ret)
localStorage.setItem('_list', ret)
}
}
複製代碼
getters.js 數據計算輸出
export const list = state => state.list
export const tempList = state => state.tempList
export const whiteUser = state => state.list.filter(item => (/白/g).test(item.nickname))
複製代碼
在 .vue 中使用 vuex
數據, 咱們能夠在計算屬性(computed)中先定義
computed: {
list() {
return this.$store.getters.list;
},
tempList() {
return this.$store.getters.tempList;
},
whiteUser() {
return this.$store.getters.whiteUser;
}
}
複製代碼
再後來於組件中正常訪問便可
<template>
<div class = "list">
<div class="item" v-for="(user, index) in list" :key="index"> {{ user.nickname }} </div>
</div>
</template>
複製代碼
組件中提交 mutations & 分發 actions
export default {
methods: {
setListData() {
const data = [
{ nickname: '小白1', age: 18 },
{ nickname: '小白2', age: 17 },
{ nickname: '小黑', age: 19 }
]
// 組件中 提交 mutations
this.$store.commit("SET_LIST", list);
},
getListAndSetData() {
// 組件中 分發 actions
this.$store.dispatch("getListAndSet", {
page: 1,
limit: 20
});
}
}
}
複製代碼
輔助函數 映射 vuex 數據/方法到局部組件中【喜歡就用: 推薦】
import { mapGetters, mapMutations, mapActions } from "vuex";
export default {
methods: {
setListData() {
const data = [
{ nickname: '小白1', age: 18 },
{ nickname: '小白2', age: 17 },
{ nickname: '小黑', age: 19 }
]
this.SET_LIST(list);
},
getListAndSetData() {
this.getListAndSet({
page: 1,
limit: 20
});
},
// mapMutations & mapActions 都在 methods 中進行映射
...mapMutations(["SET_LIST"]),
...mapActions(["getListAndSet"])
},
computed: {
// mapState & mapGetters 都在 computed 中進行映射
...mapGetters(["list", "tempList", "whiteUser"])
}
}
複製代碼
輔助函數參數還能夠是對象
export default {
methods: {
setListData() {
const data = [
{ name: '小白1', age: 18 },
{ name: '小白2', age: 17 },
{ name: '小黑', age: 19 }
]
this.setList(data) // 提交 mutations 設置列表數據
},
// 輔助函數接收對象形式,其它函數形式也是如此
...mapMutations({
setList : 'SET_LIST',
})
}
}
複製代碼
若是項目夠大/複雜 vuex 的 Module 就能夠發揮巨大做用
# 基本目錄結構
|-- store
|-- modules
|-- global.js
|-- test.js
|-- index.js
|-- types.js
# 固然, 咱們能夠細分每一個模塊
複製代碼
store 入口文件
import Vue from 'vue'
import Vuex from 'vuex'
// 管理模塊
import test from './modules/test'
import global from './modules/global'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
test,
global
},
})
export default store;
複製代碼
types.js
export const SET_LIST = 'SET_LIST';
export const SET_TEMP_LIST = 'SET_TEMP_LIST';
// global
export const SET_TOKEN = 'SET_TOKEN'
複製代碼
modules/test.js
// test module
import * as types from '../types';
import axios from "axios"
const state = {
list: [],
tempList: []
}
const mutations = {
[types.SET_LIST](state, list) {
state.list = list
},
[types.SET_TEMP_LIST](state, list) {
state.tempList = list
}
}
const actions = {
async getListAndSet({ commit }, queryParams) {
const ret = await axios.get('api/test/test1', {
params: queryParams
}).then(res => res.data.data)
commit(types.SET_LIST, ret)
commit(types.SET_TEMP_LIST, ret)
localStorage.setItem('_list', ret)
}
}
const getters = {
list: state => state.list,
tempList: state => state.tempList,
whiteUser: state => state.list.filter(item => (/白/g).test(item.nickname))
}
export default {
state,
actions,
getters,
mutations
}
複製代碼
全局命名空間 的模塊化,咱們能夠按照以往方式正常得到屬性或方法, 由於它們都默認被註冊於全上.
考慮模塊理應具備封裝/複用性, 不喜歡命名上有所衝突, 因此
爲 vuex 模塊添加命名空間時,咱們須要探討的幾個問題
給vuex模塊添加命名空間&訪問全局命名空間內容
/** * 添加命名空間的vuex模塊的actions&getters的參數對象選項中會自動添加 rootState/rootGetters 方便咱們訪問全局屬性 * 添加命名空間的vuex模塊的actions中想要訪問全局下的 dispatch 或 commit, 須要賦予第三個參數 { root: true } 表示受權 */
import * as types from '../types';
import axios from "axios"
const state = {
listNameSpace: []
}
const mutations = {
["SET_LIST"](state, list) {
state.listNameSpace = list
}
}
const actions = {
// 帶命名空間的 module 中 dispatch 和 commit 都被局部化,能夠經過第三個參數對象 {root: true} 訪問
// 參數對象中會自動添加參數 rootState rootGtters, 分別表示全局下的數據
async getListAndSetNamespace({
dispatch,
commit,
rootState,
rootGetters
}, queryParams) {
const ret = await axios.get('api/test/test1', {
params: queryParams
}).then(res => res.data.data)
commit('SET_LIST', ret) // 訪問局部的 test_namespace/SET_LIST
commit("SET_LIST", ret, { root: true }) // 訪問全局下的 SET_LIST
dispatch("getListAndSet", ret, { root: true }) // 訪問全局下的 getListAndSet
console.log('rootState: ', rootState)
console.log('rootGetters: ', rootGetters)
}
}
const getters = {
// 帶命名空間的 module 中 state 和 getters 都被局部化, 會自動添加 第三個參數(rootState)第四個參數(rootGetters)能夠經過它們訪問全局屬性
ListNameSpaceGetters(state, getters, rootState, rootGetters) {
return rootGetters.tempList
}
}
export default {
namespaced: true,
state,
actions,
getters,
mutations
}
複製代碼
在組件中訪問帶命名空間的vuex模塊
<template>
<div>
ListNameSpaceGetters: {{ ListNameSpaceGetters }}
<van-button @click="namespaceGetDataAndSetData">局部組件的actions調用</van-button>
</div>
</template>
複製代碼
import { mapGetters, mapActions } from "vuex";
export default {
name: "test",
data() {
return {};
},
methods: {
namespaceGetDataAndSetData() {
this.getListAndSetNamespace()
},
...mapActions({
getListAndSetNamespace: 'test_namespace/getListAndSetNamespace'
})
},
computed: {
...mapGetters({
listNameSpaceGetters: "test_namespace/ListNameSpaceGetters"
})
}
};
複製代碼
vuex 日誌使得咱們能夠在 console 愉快地查看對 vuex 的操做
// store 入口文件中添加 4 行代碼
import Vue from 'vue'
import Vuex from 'vuex'
// 管理模塊
import test from './modules/test'
import global from './modules/global'
import createLogger from 'vuex/dist/logger' // 1
Vue.use(Vuex)
const debug = process.env.NODE_ENV !== 'production' // 2
const store = new Vuex.Store({
modules: {
test,
global
},
// vuex工具
strict: debug, // 3
plugins: debug ? [createLogger()] : [] // 4
})
export default store;
複製代碼
筆記僅供參考, 若有錯誤還請朋友們不吝指出.