什么是vuex?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
具体的说,就是把组件的共享状态抽离出来,以一个全局单例模式管理,这就是vuex
什么时候使用vuex?
- 多个视图依赖同一个状态
- 来自不同视图的行为需要变更同意状态
vuex核心概念
- state
state里面存储着所有的共享状态,也就是需要被多个组件所共享的数据,从store中读取状态最简单的方法就是在计算属性中返回某个状态
//store/index.js中
export default new Vuex.Store({
state: {
count: 10
}
});
//某个组件中
computed:{
count(){
return this.$store.state.count
}
}
- mutations
在使用vuex时,不能直接通过this.$store.state.count直接修改count的值,想要修改count唯一的办法就是在mutations中修改count值,然后在组件中提交mutations,这也体现也vuex的“一切状态可预测”的思想,因为mutations中改变count的方法是固定的,每次只能加1,这就是”可预测“
//store/index.js
export default new Vuex.Store({
state: {
count: 10
},
mutations: {
addCount(state) {
state.count ++
}
}
});
//组件中
methods:{
add(){
this.$store.commit('addCount') //提交mutations
}
}
- getter
getter可以认为是store中的计算属性,就像计算属性一样,getter的返回值会根据他的依赖被缓存起来,且只有当他的依赖值发生变化时才会被重新计算,他的第一个参数是state,还可以接受其他getter作为第二参数
//store/index.js
getter:{
getCount(state){
return state.count + 10
}
}
- actions
actions类似于mutations,也是用来改变state状态的,但是actions不是直接修改state状态,而是通过提交mutations,同样都是修改state状态,mutations中用于执行同步操作,actions中用于执行异步操作,在组件中提交actions时使用this.$store.dispatch
//store/index.js
export default new Vuex.Store({
state: {
count: 10
},
mutations: {
addCount(state){
state.count ++
}
},
actions:{
addCountSync(context){
setTimeout(() => {
context.commit('addCount')
}, 2000);
}
}
});
//组件中
methods:{
addCountSync(){
this.$store.dispatch('addCountSync')
}
}
参数context中有这些属性
- module
当项目比较大时,相应的状态也会比较多,如果都放在一个对象中会很复杂,不过vuex支持模块化,可以很好的解决这个问题
这里官网说的很容易理解,直接贴地址了https://vuex.vuejs.org/zh/guide/modules.html
接下来是一个简单的demo
假设小A和小B分组去统计班级里同学姓名,有一份签到表,小A统计过的人,小B能在签到表中看到,小B统计过的人,小A也能在签到表中看到,这样就防止重复统计,也就是说他们俩维护着同一份数据,(组件间通信)
安装vuex
npm install vuex --save
在vue中引入,新建一个store目录,在其下新建index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
});
在main.js中引入,并挂载到vm中
import store from "./store/index.js";
new Vue({
router,
store, //挂载store
render: h => h(App)
}).$mount("#app");
创建两个组件,过程就不说了,他俩是兄弟组件,不能直接通信,但却要维护同一份名单
在没有使用vuex的情况下,值的传递过程是这样的,以父组件为媒介进行组件间传值,父子组件传值本来就挺麻烦的,这样一捣腾就巨麻烦了,这还只是一层嵌套,当有多级父子嵌套时就该砸电脑了
接下来我们看看使用vuex的情况,可以在任意组件间共享数据,操作都是一样的,不会因为嵌套而变得复杂
接着上面的demo,A、B组件所要共享的数据是一份签到名单,可以在名单上增加名字,也可以删除名字,所以我们需要一个数组names来保存名单,一个addName方法增加名字,一个delName方法删除名字
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
names: []
},
mutations: {
addName(state, name) {
state.names.push(name);
},
delName(state, name) {
let index = state.names.indexOf(name);
state.names.splice(index, 1);
}
}
});
在组件中触发事件时提交相应的mutations即可
methods:{
addName(){
this.$store.commit('addName', this.stu)
this.stu = ""
},
delName(e){
this.$store.commit('delName', e.target.dataset.name)
}
},
vuex辅助函数
每次都写this.$store.state.prop、this.$store.commit() 、this.$store.dispatch比较麻烦,所以vuex提供了几个辅助函数来化简其写法,这些函数返回的都是一个对象,结合ES6的扩展运算符的话就会更加简洁
- mapState()
- mapMutations()
- mapActions()
- mapGetters()
import {mapState} from 'vuex'
export default {
computed:{
...mapState(["names"]) // mapGetters类似
},
methods:{
...mapMutations(["delName"]),//不能在这里传参,所以要多写一个del函数来调用这个delName函数 mapActions类似
del(e){
this.delName(e.target.dataset.name)
}
}
}