前言
Vuex是一个专为 Vue.js 应用程序开发的状态管理模式。但是无法持久化,页面刷新即消失;
有错误的地方欢迎指正~
开始
- 创建vuex仓库 如
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// 创建仓库
export default new Vuex.Store({
state: {count:0},
mutations: {
increment(state) {
state.count++
}
}
});
- 在main.js里面引入仓库
import store from './store/index.js';
五个属性
state、getters、mutations、actions、modules。
- state:vuex的基本数据,用来存储变量
- getters:从基本数据(state)派生的数据,相当于state的计算属性
- mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数,提交载荷作为第二个参数。
- action:和mutation的功能大致相同,不同之处在于==》1.Action提交的是mutation,而不是直接变更状态。2.Action可以包含任意异步操作。
- modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
state
state就是数据源存放地,对应于一般Vue对象里面的data。state里面存放的数据是响应式的,Vue组件中从store中读取数据,若是store中的数据发生了改变,依赖这个数据的组件也会发生改变。
使用
在组件中使用时,最好放在计算属性中,这样在state变化时,页面也能动态渲染
computed: {
getCount() {
return this.$store.state.count;
}
}
若需要获取多个状态,都设置为计算属性会使代码冗余,mapState辅助函数能解决这个问题
mapState辅助函数
mapState函数返回的是一个对象
在组件中使用,解决冗余问题
import {mapState} from 'vuex';
computed: mapState(
{
// this.computedCount === store.state.count
computedCount: state => state.count,
// this.nameCount === store.state.count
nameCount: 'count'
}
)
或
computed: mapState(
// this.count === store.state.count
['count'],
)
扩展运算符
辅助函数与局部计算属性一起使用
computed: {
...mapState(
{
// this.computedCount === store.state.count
computedCount: state => state.count,
// this.nameCount === store.state.count
nameCount: 'count'
}
)
}
getters
从state 中派生出一些状态,可以看成计算属性,可以通过属性或函数的方式访问获取
属性访问与方法访问
getters: {
// 属性访问
count100: (state) => state.count + num,
// 方法访问
count_num_x100: state => number => state.count * number * num
},
computed: {
// 属性访问
count100() {
return this.$store.getters.count100;
},
// 方法访问
count_num_x100() {
return this.$store.getters.count_num_x100(2);
}
}
mapGetters 辅助函数
用法与mapState类似
mutations
- 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
- 注意Mutations里面的函数必须是同步操作,不能包含异步操作
mutations: {
increment(state) {
state.count++;
},
incrementNum(state, number) {
state.count += number;
}
}
methods: {
incrementCount() {
this.$store.commit('increment');
},
incrementCountNum() {
this.$store.commit('incrementNum', 20);
}
}
mapMutations辅助函数
methods: {
...mapMutations([
'increment',
'incrementNum'
]
}
<button class="fd-btn-a" @click="increment">count++</button>
<button class="fd-btn-a" @click="incrementNum(20)">incrementNum++</button>
actions
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
- Action 通过 store.dispatch 方法触发:
actions: {
incrementAsync({commit}) {
setTimeout(() => {
commit('increment');
}, num * num2);
}
}
incrementAsync() {
this.$store.dispatch('incrementAsync');
}
mapActions 辅助函数
使用方法与mapState类似
组合 Action
store.dispatch 可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
actions: {
incrementAsync({commit}) {
return new Promise((resolve) => {
setTimeout(() => {
commit('increment');
resolve();
}, num * num2);
});
}
}
incrementAsync() {
this.$store.dispatch('incrementAsync').then(() => {
alert(1);
});
}
module
- 当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter。
- 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:
使用模块中的state、getters,mutation,action
注意,除了state以外,所有的getters、mutation、actions都是全局的,使用方式与全局使用方式一致,若要将所有属性都局部化,模块定义里定义namespaced: true即可,以下使用都是namespaced: true的情况下的使用方式:
// state
countA: state => state.a.count
// getters
this.$store.getters['a/count100']
// mutations
increment: 'a/increment',
// ations
incrementAsync() {
this.$store.dispatch('a/incrementAsync').then(() => {
alert('a');
});
this.$store.dispatch('b/incrementAsync').then(() => {
alert('b');
});
}
模块嵌套
在模块中直接写嵌套
在moduleB中嵌套moduleC
const moduleC = {
namespaced: true,
state: {count: 3},
getters: {count100: (state) => state.count * num}
};
若模块c没有定义namespaced,那么c可以访问b的命名空间,c可以使用b中的getters等
通过动态注册嵌套
store.registerModule(['b', 'c'], {state: {count: 3}});
严格模式
- 开启strict:true,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。