注意安装命令如下:
npm i vuex@3
main.js 注入
import store from './store'
new Vue({
el: '#app',
store
})
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
// 是否显示
visible: true
},
mutations: {// 同步操作,可修改
setVisible (state, value) {
state.visible = value
},
},
getters: {// 可以认为是 store 的计算属性
getVisible(state) {
return state.visible;
}
},
actions: {// 异步操作,不可修改,交给mutations
setVisibleAction ({commit},payload) {
commit("setVisible",payload)
},
},
modules: {
}
})
计算属性中使用
computed: {
close: {
set (value) {
/ 两种方式,1. commits是同步;2. dispatch 是异步
// return this.$store.commit('setVisible', value)
return this.$store.dispatch('setVisibleAction', value)
},
get () {
// 两种方式,1. getter;2. state
// return this.$store.getters.getVisible
return this.$store.state.visible
},
}
}
mapState
辅助函数帮助我们生成计算属性;
mapGetters
辅助函数仅仅是将 store 中的 getter 映射到局部计算属性;
mapMutations
辅助函数将组件中的 methods 映射为 store.commit
调用(需要在根节点注入 store
);
mapActions
辅助函数将组件的 methods 映射为 store.dispatch
调用(需要先在根节点注入 store
);
Vuex 使用单一状态树,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态。有如下四种常用方式:
函数
computed: {
count() {
return this.$store.state.count;
}
}
get 函数
computed: {
count: {
get() {
return this.$store.state.count;
}
}
}
mapState
对象方式。注意在 .vue 文件中要 import
import { mapState } from 'vuex'
computed: mapState({
count: state => state.count
})
mapState
数组方式。注意在 .vue 文件中要 import
import { mapState } from 'vuex'
computed: {
// mapState 对象方式
...mapState({
count: state => state.count
})
}
此处就不举例说明了,详见官网说明。官网有如下解释,请仔细阅读理解:
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
使用 $store.getters
对象
this.$store.getters.getVisible
改变 store
的状态,唯一的方法是提交 mutation
。且mutation
必须是同步函数;
建议第二个参数是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读;
export default new Vuex.Store({
state: {
// 是否显示
visible: true
},
mutations: {// 同步操作,可修改
setVisible (state, value) {
state.visible = value
},
}
})
this.$store.commit('setVisible', false)
store.dispatch
可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch
仍旧返回 Promise:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
store.dispatch('actionA').then(() => {
// ...
})
模块具有更高的封装度和复用性。通过添加 namespaced: true
的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
目录结构如下:
└── src
└── store
├── modules(可有多个js)
│ ├── user.js
│ └── info.js
├── getters.js
└── index.js
modules/user.js
// 状态
const state = {
token: getToken(),
name: getUser()
}
// 同步设置
const mutations = {
// token
SET_TOKEN: (state, token) => {
state.token = token;
},
// name
SET_NAME: (state, name) => {
state.name = name;
}
}
// 异步设置
const actions = {
// 登录
login({ commit }, userInfo) {
const { form, axios } = userInfo;
return new Promise((resolve, reject) => {
let url = '/v1/auth/login';
axios.post(url, form).then((resp) => {
if (resp.succ) {
commit('SET_TOKEN', resp.token);//设置token
commit('SET_NAME', resp.user);//设置用户名
resolve();
} else {
reject(resp)
}
});
})
},
// 登出
logout({ commit, state }) {
// TODO
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
getters.js
const getters = {
// TODO
}
export default getters
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
const modulesFiles = require.context('./modules', true, /\.js$/)
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
const value = modulesFiles(modulePath)
modules[moduleName] = value.default
return modules
}, {})
const store = new Vuex.Store({
modules,
getters
})
export default store
main.js
中引入,代码 3、6 行。
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
store,
render: h => h(App)
}).$mount('#app')