在现代前端开发中,组件化已成为一种广泛采用的开发模式。然而,当多个组件需要访问相同的数据时,如何进行高效的数据共享成为一个挑战。为了解决这个问题,Vuex 应运而生。Vuex 是一种实现组件全局状态管理的机制,能够方便地实现组件之间数据的共享。本文将介绍 Vuex 的基本概念、集中管理共享数据的功能及其优势,以及何时适合将数据存储到Vuex中。读者将对Vuex有更清晰的认识,并能够更好地利用它来管理和共享数据。
1.认识Vuex
Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
用 Vuex统一管理状态的好处:
- 1.能够在 Vuex 中集中管理共享的数据,易于开发和后期维护。
- 2.能够高效地实现组件之间的数据共享,提高开发效率。
- 3.存储在 Vuex 中的数据都是响应式的,能够实时保持数据与页面的同步。
什么样的数据适合存储到Vuex中:
一般情况下,只有组件之间共享的数据,才有必要存储到 Vuex 中;对于组件中的私有数据,依旧存储在组件自身的data中即可。
2.Vuex的引入
(1)安装vue依赖包
npm i vuex@3.2.0 --save
本文所采用的是Vue2版本,所以这里使用3.2.0版本Vuex,其他版本请参考:官方文档
(2)创建store对象
在store/index.js中导入Vuex包并创建store对象:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store=new Vuex.Store({
//state中存放的就是全局共享的数据
state:{count:0}
})
export default store
(3)挂载store
在main.js中导入store对象并挂载到vue实例中:
import store from './store'
new Vue({
render: h => h(App),
store
}).$mount('#app')
3.Vuex的基本使用
(1)State
State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行存储
组件访问state中数据的第一种方式:
this.$store.state.全局数据名称
组件访问state中数据的第二种方式:
1.从vuex中按需导入mapState函数:import {mapState} from 'vuex'
2.将全局数据,映射为当前组件的计算属性:computed:{...mapState(['count'])}
3.直接使用count即可
<template>
<div>
<div>{{this.$store.state.count}}</div>
<div>{{count}}</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
computed: {
...mapState(['count'])
}
}
</script>
(2)Mutation
Mutation用于变更Store中的数据
1.只能用mutation变更Store数据,不可以直接操作Store中的数据
2.通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
//定义Mutation
const store = new Vuex.Store({
state: {count: 0},
mutations: {
add(state) {
//变更状态
state.count++
},
//可以在触发mutations时传递参数
addN(state, step) {
state.count += step
}
}
})
同样,触发mutations也有两种方式:
//触发mutations的第一种方式
//commit 的作用 就是调用某个mutation函数
this.$store.commit('add')
this.$store.commit('addN',3)
//触发mutations的第二种方式
//从vuex中按需导入mapMutatuons函数
import {mapMutatuons} from 'vuex'
//将指定的mutations函数,映射为当前组件的methods函数
methods:{
...mapMutations(['add','addN'])
}
注意:
1.不建议直接在组件中操作store中的数据,这样写是不对的:this.$store.state.count++
2.不要在mutations函数中,执行异步操作
(3)Action
Action用于处理异步任务
如果通过异步操作变更数据,必须通过Actioin,而不能使用Mutation,但是在Action中还是要通过触发Mutation的方法变更数据
//定义Action
const store=new Vuex.Store({
state:{count:0},
mutations:{
add(state){
state.count++
},
addN(state, step) {
state.count += step
}
},
actions:{
addAsync(context){
setTimeout(()=>{
//在actions中 不能直接修改state中的数据
//必须通过 context.commit()触发某个mutation
context.commit('add')
},2000)
},
addAsyncN(context,step){
setTimeout(()=>{
//在actions中 不能直接修改state中的数据
//必须通过 context.commit()触发某个mutation
context.commit('addN',step)
},2000)
}
}
})
同理,触发action的两种方式:
//触发Action的第一种方式
//这里的dispatch函数 专门用来触发action
this.$store.dispatch('addAsync')
this.$store.dispatch('addAsyncN',3)
//触发actions的第二种方式
//从vuex中按需导入mapActions函数
import {mapActions} from 'vuex'
//将指定的actions函数,映射为当前组件的methods函数
methods:{
...mapActions(['addAsync','addAsyncN'])
}
(4)Getters
Getter用于对Store中的数据进行加工处理形成新的数据
1.Getter可以对Store中已有的数据加工处理之后形成新的数据,类似Vue的计算属性
2.Store中数据发生变化,Getter的数据也会跟着变化
const store=new Vuex.Store({
state:{count:0},
getters:{
showNum(state){
return '当前最新的数量是['+state.count+']'
}
}
})
同理,使用getters的两种方式:
//使用getters的第一种方式:
this.$store.getters.showNum
//使用getters的第二种方式:
import {mapGetters} from 'vuex'
computed:{
...mapGetters(['showNum'])
}
(5)Modules
Module是store分割的模块,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
这里将上述的store单独抽离到app.js文件中:
// store/app.js 文件
const state = {
count: 0 // 需要管理的状态数据
}
const mutations = {
addN(state, step) {
state.count += step
}
}
const actions = {
addAsyncN(context, step) {
setTimeout(() => {
context.commit('addN', step)
}, 2000)
}
}
const getters = {
showNum(state) {
return '当前最新的数量是[' + state.count + ']'
}
}
export default {
namespaced: true, // 为了解决不同模块命名冲突的问题
state,
mutations,
getters,
actions
}
此时,index.js代码如下:
// store/index.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
import app from './app.js'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
modules: { // 子vuex状态模块注册
namespaced: true,
app,
}
})
export default store
在vue文件中使用state、mutation、action、getters的方法如下:
// 使用state
this.$store.state.app.count
// 使用mutation
this.$store.commit('app/addN', 3)
// 使用action
this.$store.dispatch('app/addAsyncN', 3)
// 使用getters
import {mapGetters} from 'vuex'
computed: {
...mapGetters({
showNum: 'app/showNum'
})
}
注意:这里在使用他们时都需要指明所在的命名空间。state、mutation、action的两种使用方法仍然有效,但getters只能通过mapGetters函数使用。






