Vuex状态管理(上)
文章目录
一.概念
vue官方提供的状态管理器.用于处理全局的数据共享问题的.
状态:即数据、视图。状态管理的本质,就是对应用程序的数据进行科学地流程化管理,目标是让数据变化可预期、可控。Flux一种数据管理架构方案,这是一种数据管理的思想,最早诞生于React团队。
- React技术栈中,最出名的状态管理工具是 Redux和Mobx。
- Vue技术栈中,最出名的状态管理工具是Vuex。
Vuex只是一种数据管理方案,并不是Vue开发必须的。换句话说,在架构Vue项目时可以不使用Vuex。
虽然可以不使用Vuex,但不得不说Vuex非常强大,所以还是建议尽量用上它。Vuex常用于实现组件之间的数据交互、程序数据缓存等需求。Vuex配合devtools,可以非常方便地调试应用程序中的数据bug。
之前我们学习Vue的时候,各种组件之间传值,比如props传值,状态提升传值,事件总线,还有通过emit事件回传等等.那我们这里引入的Vuex,就是组件之间数据交互的终极解决方案.
二.Vuex的仓库的五大核心概念
1.state
state是Vuex的数据存储中心
放在state中的数据,所有组件都可以共享,并且保持同步,只要state中的数据发生变化,视图中自动更新页面状态.
2.getters
getters可以理解为组件中的计算属性
放在getters关联的state,只要发生变化,getters 会自动更新
3.mutations
唯一能够修改state数据的东西,不允许写异步代码
mutation直接同步的修改state的主要入口!在组件中使用this.$store.commit(‘已定义的mutaation方法’,‘负载’)来触发mutation方法
4.actions
间接的异步修改state,在actions里面的方法都是异步,比如调接口,定时器等.
实际上在actions中可以直接修改state,但是这样做在devtools没有修改的记录,非常不方便于调试
vuex官方建议:只用mutations来修改state,不要使用actions来修改state
5.module
仓库模块的拆分
三.安装与使用
1.安装
npm install vuex -S
2.使用
在src目录中新建一个名为store.js的文件,然后引入vue,vuex,并注册vue.use(vuex)
//引入vue
import Vue from 'vue';
//import Vuex
import Vuex from 'vuex';
//注册Vue.use();
Vue.use(Vuex);
const store = new Vuex.Store({
//Vuex的数据存储中心
state:{
},
//组件中的计算属性
getters:{
},
//唯一能够修改state数据的东西,不允许写异步代码
mutations:{
},
//间接的异步修改state,在actions里面的方法都是异步,比如调接口,定时器等.
actions:{
},
//仓库模块的拆分
modules:{
}
});
export default store;
3.main.js引入并挂载
//引入store
import store from './store';
new Vue({
router,
store,//挂载store.js
render: h => h(App),
}).$mount('#app')
4.验证是否安装成功
console.log(this.$store);
在任何地方,输出this.$store即可,比如App.vue的钩子函数mounted
5.组件中如何使用state和getters
1.方法一
使用挂载到Vue原型上的 store对象就是new Vuex.Store()生成的仓库实例对象
console.log(this.$store.state.xxxxxx);
console.log(this.$store.getters.yyyyy);
2.方法二(推荐) computed
使用computed,计算属性,实际上就是将方案一中获取到的数据给计算属性
computed: {
xxxxxx: function() {
return this.$store.state.xxxxxx;
},
yyyy: function() {
return this.$store.getters.yyyyy;
}
},
3. 方法三(推荐) vuex 辅助函数
就是方案二中的一种优雅写法,可以认为是语法糖
组件中从vuex中引入你需要的辅助函数
调用辅助函数,并将其返回的值赋给组件的computed选项
import { mapState, mapGetters } from "vuex";
export default {
computed: {
...mapState(["xxxx", "yyyyy"]),
...mapGetters(["culecount"]),
}
}
mapState的语法和mapGetters语法
// mapState 接收一个数组做为参数,参数中的每一项,就是在仓库中的 state 数据
mapState([state1, state2, state3])
// mapGetters 接收一个数组做为参数,参数中的每一项,就是在仓库中的 getter 数据
mapGetters([getter1, getter2])
使用计算属性和辅助函数取值时的区别?
二者效果一样,但是在VueDevtools中的表现不一样
使用计算属性时,插件中显示的是computed
使用辅助函数时,插件中显示的是vuexbindings
虽然效果一样,但是我们一般推荐使用辅助函数的形式!!!
computed: {
//推荐使用展开运算符
...mapState(["count", "msg"]),
...mapGetters(["culecount"]),
xxxxxx: function() {
return this.$store.state.count;
},
yyyy: function() {
return this.$store.getters.culecount;
}
},
6.组件中如何修改state与getters的数据
首先要明确一点:state可以修改,getters是不能被修改的
步骤:
- 仓库中要提供对应 state修改的mutation函数
- 在组件中去调用mutation
调用mutationd 的2种方式:
1.方法一
直接使用vuex绑定到vue原型上的$store对象的commit()方法
this.$store.commit()
//在仓库中的 mutations中定义方法
mutations: {
//在mutation中定义一个改变state里参数的方法
updateCount(state, payload) {
state.count += payload.count;
}
}
//在相应的组件中触发这个函数
methods: {
clickhandle() {
// 不建议直接改vuex里的state,虽然可以改,但是不建议
//this.$store.state.count++;
let payload = {
count: 10
};
// 向store提交一个名叫updateCount的mutation方法,申请同步改变count
this.$store.commit("updateCount", payload);
},
}
2.方法二(推荐) vuex 辅助函数
使用vuex的辅助函数,mapMutations和
//在仓库中的 mutations中定义方法
mutations: {
updateCount(state, payload) {
state.count += payload.count;
},
updateMsg(state,payload){
state.msg=payload;
}
},
//类似解构赋值
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
//在组件中使用vuex辅助函数
methods: {
//推荐使用展开运算符
...mapMutations(["updateCount", "updateMsg"]),
...mapActions(["asyncUpdateCount", "asyncUpdateMsg"]),
//因展开运算符展开的方法,无法传参,所以这里可以使用一个函数做中转
update() {
let payload = {
count: 10
};
this.updateCount(payload);
},
所有的mutation执行,都能在VueDevtools看到
为何vuex中的state必须使用mutation来修改呢?
- 为了以一种可以预见的方式去修改数据,不至于让数据难以理解,虽然可以通过$store对象直接修改,但是在严格模式下会报错,并且VueDevtools无法跟踪到数据,不方便调试
- 为了实现调试插件(VueDevtools)的时间旅行机制
7.使用actions异步修改state数据
首先要知道,mutation里面只允许同步的去修改state数据,
其实mutation中可以异步的去修改state数据,不会报错,但是会导致调试插件的时间旅行等机制没有效果
处理异步修改state数据有两种方式
-
1.不涉及action,直接在组件上的methods方法中写异步代码,然后再调用mutation
-
2.涉及action
使用action,首先需要在actions选项中定义action函数
注意:action中不能直接去修改state,要修改state,必须使用当前上下文对象的commit()去执行某个mutation来修改
使用涉及action修改数据的方式也有两种
1.方法一
在仓库中的action中通过commit调用mutation中的方法,然后异步处理,然后在需要调用的组件内部methods选项中,通过 this.$store.dispatch()来派发
// actions:间接地异步地修改state
// 在actions里面的方法,都是异步,比如调接口、定时器等
// 在actions中可以直接state,但这样做在devtools没有修改的记录,非常不便于调试
// Vuex官方特别建议,只用mutations来修改state,不要使用actions来修改state
actions: {
asyncUpdateCount(store, payload) {
setTimeout(() => {
store.commit('updateCount', payload)
}, 2000);
}
}
//组件中
methods: {
clickAsyncHandle() {
let payload = {
count: 10
};
// 向store提交一个名叫asyncUpdateCount的actions方法,申请异步改变count
this.$store.dispatch("asyncUpdateCount", payload);
}
}
2.方法二
使用Vuex中的辅助函数 mapActions
//类似解构赋值
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
methods: {
...mapMutations(["updateCount", "updateMsg"]),
...mapActions(["asyncUpdateCount", "asyncUpdateMsg"]),
}
使用方式与上面mutation的方法基本一致!