Vuex状态管理机
1 介绍
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
应用场景:同级别组件之间通讯
,比如如下所示:
let comA = {}
let comB = {}
2 基本使用
2.1 state
state(类似于vue实例中data) state组件里面存放共享数据
,将每个vue实例中的公共变量抽取出来进行统一管理
。
state: {
msg: 'hello vuex'
}
//在vue中,通过计算属性获取存储在vuex的状态,可以直接获取,也可以通过辅助函数获取
computed: {
count() {
return this.$store.state.count
}
// 或者
...Vuex.mapState(["count"])
}
2.2 getters
getters(类似于vue实例中的computed),在获取state后,对state数据处理之后再返回,它属于一种方法
,用于将state中静态的数据经过计算再返回
。
getter: {
//参数是默认参数 --派生自state
reMsg(state) {
返回操作之后的结果
return state.msg.toUpperCase()
}
}
在vue中,可以通过计算属性访问
computed: {
reMsg() {
return this.$store.getters.reMsg
}
// 或者
...Vuex.mapGetters(["reMsg"])
}
2.3 mutations(突变)
mutations是唯一修改state数据的方式
,一般用来做一些同步
操作,更改Vuex的store中的状态的唯一方法是提交 mutation
,必须是同步操作。mutation函数的第一个参数为state
,第二个参数是来接受在调用mutation的时候用户传递的实参
。
mutations: {
SET_MSG(state, payload) {
state.msg = payload
}
}
可以在vue生命周期钩子中提交突变或者在methods中映射突变方法
created() {
// 参数一是突变方法的名字,参数二是传递的实参
this.$store.commit('SET_MSG', 'hello mutation')
}
methods:{
...Vuex.mapMutations(['SET_MSG'])
}
2.4 actions(动作)
actions用来存放异步请求
方法,action提交的是 mutation,从而间接的变更state中的状态。actions中的异步请求接受一个形参-context(上下文对象)
(1)context.state获取state
(2)context.getters获取getters
(3)context.commit()提交突变
(4)context.dispatch()分发动作
actions: {
async findAll(context) {
let res = await axios.get('http://...');
// 提交突变
context.commit('SET_MSG', res.data.data)
}
}
可以在vue生命周期钩子中分发动作或者在methods中映射actions中的方法
created() {
// 参数一是异步函数的名字,参数二可以传递实参
this.$store.dispatch('findAll')
}
methods:{
...Vuex.mapActions(['findAll'])
}
2.5 案例-定义状态机实例
<title>vue</title>
<script src="../js/vue.js"></script>
<script src="../js/vuex.js"></script>
</head>
<body>
<div id="app">
<h3>{{data1}}</h3>
<h4>
vuex-state-{{msg}}
<button @click="$store.commit('SET_MSG','再见vuex')">修改状态机按钮</button>
</h4>
<h5>vuex-getters-{{upperMsg}}</h5>
<ul>
<li v-for="(item,index) in categories" :key="index">
栏目编号:{{item.id}}
栏目名称:{{item.name}}
</li>
</ul>
</div>
<script>
// 1.声明Vuex实例
let store = new Vuex.Store({
state:{
msg:'this is vuex data',
categories:[]
},
getters:{
upperMsg(state){
return state.msg.toUpperCase()
}
},
// 状态机内部状态的变更
mutations:{
// 突变是修改state中数据的唯一方法
// 突变方法中接受两个形参 第一个是state 第二个是调用突变时传递的实参
SET_MSG(state,payload){
state.msg = payload;
},
SET_CATEGORIES(state,payload){
state.categories = payload;
}
},
actions:{
// 动作,用来存放组件共享的异步方法
// context上下文对象
async findAllCategories(context){
// es6
// let res = await ajax ()
let res = {
status:200,
message:'查询成功',
data:[
{id:1,name:'校园新闻'},
{id:2,name:'校园资讯'},
{id:3,name:'娱乐新闻'},
{id:4,name:'校园新闻'},
],
timestamp:1634817659543
}
// 提交突变,来修改状态机内部的数据
console.log(context);
// 通过commit()方法来提交突变 第一个参数是突变函数的名字 第二个是突变函数的实参
context.commit('SET_CATEGORIES',res.data)
}
}
})
let vm = new Vue({
el:"#app",
data:{
data1:'this is vm data'
},
computed:{
// 通过计算属性,将vuex state中的数据映射过来
msg(){
return this.$store.state.msg
},
categories(){
return this.$store.state.categories;
},
// 通过计算属性,将vuex
upperMsg(){
return this.$store.getters.upperMsg
},
},
methods:{},
created(){
// 在该钩子函数中,调用vuex状态机中的动作
// 通过dispatch()来分发动作
this.$store.dispatch('findAllCategories');
// 提交突变
// this.$.store.commit('SET_MSG','你好,状态机')
},
// 2.将状态机实例,注入到vue实例中
store:store
})
</script>
3 辅助函数
Vuex构造函数内部提供了快捷映射数据和方法的方法,使用对象的解构,将内部的辅助函数解构出来。
let { mapState, mapGetters, mapMutations, mapActions } = Vuex
使用
computed: {
...mapState(['msg']), // 状态映射
...mapGetters(['reMsg']) // 计算属性映射
},
methods: {
...mapMutations(['SET_MSG']), // 突变映射
...mapActions(['findAll']) // 动作映射
}
4.模块化开发
4.1 模块化目的
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
、甚至是嵌套子模块。namespaced表示设置命名空间
4.2 模块化使用
<title>模块化开发</title>
<script src="../js/vue.js"></script>
<script src="../js/vuex.js"></script>
</head>
<body>
<div id="app">
<div>moduleA: state-{{msg1}} getters-{{upperMsg1}}
<button @click="SET_MSG1('你好模块化A')">修改A数据</button>
</div>
<div>moduleB: state-{{msg2}} getters-{{upperMsg2}}
<button @click="SET_MSG2('你好模块化B')">修改B数据</button>
</div>
</div>
<script>
// 1.定义状态机子模块
let moduleA = {
namespaced: true,
state() {
return {
msg1: 'this is moduleA data'
}
},
getters: {
upperMsg1(state) {
return state.msg1.toUpperCase()
}
},
mutations: {
SET_MSG1(state, payload) {
state.msg1 = payload
}
},
actions: {}
}
let moduleB = {
namespaced: true,
state() {
return {
msg2: 'this is moduleB data'
}
},
getters: {
upperMsg2(state) {
return state.msg2.toUpperCase()
}
},
mutations: {
SET_MSG2(state, payload) {
state.msg2 = payload
}
},
actions: {}
}
let store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
let { mapState, mapGetters, mapMutations, mapActions } = Vuex
let vm = new Vue({
el: '#app',
data: {},
computed: {
// 在计算属性中,通过辅助函数映射vuex中的state/getters
...mapState('a', ['msg1']),
...mapState('b', ['msg2']),
...mapGetters('a', ['upperMsg1']),
...mapGetters('b', ['upperMsg2']),
},
methods: {
// 在实例的methods中通过辅助函数映射mutations
...mapMutations('a', ['SET_MSG1']),
...mapMutations('b', ['SET_MSG2']),
},
created() {
},
store
})
</script>