vue中的状态管理Vuex

106 阅读2分钟

vue中的状态管理Vuex

安装vuex

npm install vuex --save

使用vuex

src目录下新建一个store文件夹, 并在store下新建一个index.js

main.js中引入store

// main.js
import store from './store';

new Vue({
	el: App,
	store,
	render: (h) => h(App)
})
// index.js
// 引入vue
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
// 使用Vuex插件
Vue.use(Vuex);

// 暴露出store
var store = new Vuex.Store({
  state:'',
  mutations: '',
  actions: '',
  getters: '',
});
export default store;

store的组成

State

state用来定义属性

Mutations

mutations中定义了一个个的方法,用来修改属性值,因为Store不可以直接通过this.$store.state.xxx = xxx来修改属性值

mutations中的函数必须是同步操作,不能包含异步操作

Actions

actions存在的意义是假设你在修改state的时候有异步操作,vuex不希望你将异步操作放在mutations中,而是将其放在actions 中,并且将actions暴露给用户,借此操作mutations中的方法修改state

Getters

getters是读取修饰器,主要目的是在读取state时,可以加工返回值

辅助函数

Vuex中提供了4个辅助函数来帮助使用store

import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'

mapStatemapGetters只能在computed中使用,与正常的computed中的函数一起使用时需要用扩展运算符,然后在mapState或mapGetters函数的数组中放入对应的stategetters中的名称

通过辅助函数获取到的值和方法可以使用this.xxx调用

具体使用方法后面会说

按照模块拆分Store

当我们项目中数据较多,可以将数据按照功能划分为多个module

假设当前项目有一个user用户信息模块,有一个product商品信息模块

我们可以在src/store目录下新建一个components文件夹,并在components中新建一个user.jsproduct.js

// user.js
const state = {};
const mutations = {};
const actions = {};
const getters = {};
export default user = {
  namespaced: true
  state,
  mutations,
  actions,
  getters,
}

// product.js
const state = {};
const mutations = {};
const actions = {};
const getters = {};
export default product = {
  namespaced: true
  state,
  mutations,
  actions,
  getters,
}
// index.js
// 引入user和product模块
import user form './components/user.js'
import product form './components/product.js'
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

var store = new Vuex.Store({
  // 在modules属性中使用user和product
	modules: {
    user,
    product
  }
});
export default store;

namespaced属性

  • 当定义的模块module中含有namespaced: true属性时,表示开启了模块命名空间
  • 默认情况下,模块内部的sactions、mutations、getters是注册在全局命名空间的,可以直接调用,这样容易和其他模块中的state或方法名重复,所以需要添加namespaced: true来开启命名空间,区分和其他模块中冲突的state和方法。开启命名空间后访问模块中的内容需要带上模块名。

使用store(包括开启命名空间和未开启命名空间)

  • state

    • 开启命名空间 / 未开启命名空间
      1. 插值表达式使用:$store.state.模块名.属性名
      2. 映射为辅助函数 - 数组格式:...mapState('模块名', ['属性名'])
      3. 映射为辅助函数 - 对象格式:...mapState({'属性名': state => state.模块名.属性名})
      4. methods中使用:this.$store.state.模块名.属性名
  • mutations

    • 未开启命名空间
      1. this.$store.commit('mutations中方法名',实参)
      2. 映射为辅助函数 - 数组格式:...mapMutations(['mutations中方法名']])
      3. 映射为辅助函数 - 方法调用:this.mutations中方法名(参数) this['mutations中方法名'](参数)
    • 开启命名空间
      1. this.$store.commit('模块名/mutations中方法名',实参)
      2. 映射为辅助函数 - 数组格式:...mapMutations(['模块名/mutations中方法名']])
      3. 映射为辅助函数 - 方法调用: this['模块名/mutations中方法名'](参数)
      4. 映射为辅助函数 - 属性格式:...mapMutations('模块名',['mutations中方法名'])
      5. 映射为辅助函数 - 方法调用:this.mutations中方法名(参数) this['mutations中方法名'](参数)
  • actions

    • 未开启命名空间
      1. this.$store.dispatch('actions中方法名',实参)
      2. 映射为辅助函数 - 数组格式:...mapActions(['actions中方法名']])
      3. 映射为辅助函数 - 方法调用:this.actions中方法名(参数) this['actions中方法名'](参数)
    • 开启命名空间
      1. this.$store.dispatch('模块名/actions中方法名',实参)
      2. 映射为辅助函数 - 数组格式:...mapActions(['模块名/actions中方法名']])
      3. 映射为辅助函数 - 方法调用: this['模块名/actions中方法名'](参数)
      4. 映射为辅助函数 - 属性格式:...mapActions('模块名',['actions中方法名'])
      5. 映射为辅助函数 - 方法调用:this.actions中方法名(参数) this['actions中方法名'](参数)
  • getters

    • 未开启命名空间

      1. this.$store.getters.属性名
      2. 映射为辅助函数 - 数组格式:...mapGetters(['getters中方法名']])
    • 开启命名空间

      1. this.$store.getters['模块名/属性名']

      2. 映射为辅助函数 - 数组格式:...mapGetters(['模块名/getters中方法名']])

      3. 映射为辅助函数 - 方法调用: this['模块名/getters中方法名']

      4. 映射为辅助函数 - 属性格式:...mapGetters('模块名',['getters中方法名'])

      5. 映射为辅助函数 - 方法调用: this.getters中方法名

为什么Vuex要通过mutations修改state,而不能直接修改state,也不建议在actions中修改state

  1. 首先保证了store中数据的单向流动性,组件只能使用数据而不能修改数据(非生产模式),严格模式下直接修改state会报错
  2. mutations只能进行同步操作,而操作stateactions中可以是异步操作。如果异步操作state时,其他地方修改了state,会导致程序的混乱
  3. vue-devTools会记录每一次的mutations操作,可以清楚看到每一次操作后state的变化,方便调试而actions中的操作则不会被观测记录下