现在如果使用 npm 安装 vuex 默认为 Vuex4
,Vuex4
适配 Vue3
,Vuex3
适配 Vue2
npm i vuex@3
创建 store/index.js
文件
import Vue from "vue"
import Vuex from "vuex"
// 在实例化前,必须使用该插件
Vue.use(Vuex)
// 导出该对象
export default new Vuex.Store({
// 状态、数据
state: { },
// 获取、计算属性
getters: { },
// 逻辑处理
mutations: { },
// 异步请求、异步处理
actions: { }
})
import Vue from 'vue'
import App from './App.vue'
// 主文件中导入并挂载
import store from "./store/index"
// 取消生成生产提示
Vue.config.productionTip = false
new Vue({
render: h => h(App),
// 挂载 vuex
store,
}).$mount('#app')
// 挂载之后全局会多一个 $store 属性
用于状态管理,它里面的数据所有组件都可以访问,并且也是共享的
类似于组件中的 data,数据也是响应式的
组件获取:this.$store.state.xxx
state: {
// 数据
num: 2
}
对 state 中的数据进行加工处理
类似于组件中的 computed
组件获取:this.$store.getters.xxx
getters: {
getNum(state, getters){
// state:数据
// getters:自己
return state.num * 10
}
},
该方法用于逻辑处理,可以直接操作 state
类似于组件中的 methods
需要 commit(“方法名”),去触发 mutations 中的方法
mutations: {
add(state, value) {
// state:数据
// value:传入的数据
state.num += value
}
},
可以处理一些异步的数据
在 actions 中可以直接修改 state 中的值,但是官网并没有这样去建议
需要 dispatch(“方法名”),去触发 mutations 中的方法
actions: {
add(store, value) {
// store:一个不完整的 store
// value:传入的数据
// 提交任务到 mutations 中
store.commit("add", value)
}
}
上面的解释可能不太清除:
- 首先在组件中的 vuex 都需要用 $store 去获取,这个是 vue 内部实现的
- 一个基本流程是
- 在组件中调用 this.$store.dispatch(‘方法名’, 传入数据)
- actions 中的方法被触发了,然后调用 store.commit(“方法名”, 传入数据)
- mutations 中的方法被触发了,然后就可以直接去修改 state 了
- 由于 state 中的数据是响应式的,数据发生了改变默认会再次渲染视图
- 如果没有异步操作的话,其实也可以不用调用 actions 中的方法,这样可以节省一步操作
当数据量太大的时候可以使用 Module 进行模块化管理
每一个模块中都有上面四个属性
// 下面是官网的一个例子
const moduleA = {
state: () => ({ ... }),
getters: { ... },
mutations: { ... },
actions: { ... },
}
const moduleB = {
state: () => ({ ... }),
getters: { ... },
mutations: { ... },
actions: { ... }
}
export default new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
mapState:在组件中使用数据的时候要通过 this.$store.state.xxx 去获取,这样数据量多了的话,就特别的重复和冗余
当然也可以使用计算属性
// 其实这样也不太好,数据量多的话还是会写很多的东西
computed: {
xxx() {
return this.$store.state.xxx
}
}
vuex 中提供了辅助函数,可以帮助我们生成计算属性
// mapState 函数返回的是一个对象,对象中把你传入的对象变成了函数
computed: {
...mapState ({
// value:就相等于 this.$store.state.xxx
// key:这样就可以直接通过 key 去使用了
// 说白了 value 是 vuex 的,key 是组件的
key: "value",
key1: "value1",
key2: "value2"
})
}
// 比如这里返回的对象就是下面这样的,所以可以通过展开运算符,去添加到计算属性中
{
key() {
},
key1() {
},
key2() {
}
}
当映射的 key 和 value 相同时
// 也可以使用数组去展开,效果和对象一样的
computed: {
...mapState (["num","num1","num2"])
}
// 这种写法就相当于,你之前要用 this.$store.state.num 去获取数据
// 但是现在只需要用 num 去获取数据
mapGetters:和 mapState 的用法是一模一样的
mapMutations:自动帮忙调用 commit
methods: {
// 正常触发 mutations 中的方法
vcApi(){
this.$store.commit("vuexApi", 传入数据)
}
// 辅助函数,这种写法需要在调用 vcApi 这个方法的时候传入数据
...mapMutations({
vcApi: "vuexApi"
})
}
// 数组写法
methods: {
// 这种方式需要组件方法名和 mutations 中的方法名一致
...mapMutations(["Api"])
}
mapActions:自动帮忙调用 dispatch,和 mutations 使用一样
Module 文件
const moduleA = {
// 默认情况下这些属性都还是全局的,开启命名空间后变为模块的
// 开启命名空间,这里面的属性和方法,需要用当前名字的前缀才能获取
namespaced: true,
state: () => ({ ... }),
getters: { ... },
mutations: { ... },
actions: { ... },
}
export default new Vuex.Store({
modules: {
moduleA
}
})
直接获取/使用
this.$store.moduleA.state.xxx
this.$store.getters['moduleA/xxx']
this.$store.commit('moduleA/xxx', 传入数据)
this.$store.dispatch('moduleA/xxx', 传入数据)
辅助函数获取/使用
computed: {
...mapState("moduleA", {key: "value1"}),
...mapGetters("moduleA", ["num1", "num2"])
}
methods: {
...mapMutations("moduleA", {vcApi: "vuexApi"}),
...mapActions("moduleA", ["Api"])
}