在现代前端开发中,组件化已成为一种广泛采用的开发模式。然而,当多个组件需要访问相同的数据时,如何进行高效的数据共享成为一个挑战。为了解决这个问题,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函数使用。