首页 > 技术文章 > Vuex的基本使用

moringyaozheng 2020-07-02 15:20 原文

Vuex 是一个 Vue.的状态管理模式。它采用集中式存储管理应用的所有组件的状态。

基于父子、兄弟组件,我们传值可能会很方便,但是如果是没有关联的组件之间要使用同一组数据,就显得很无能为力,那么vuex就很好的解决了我们这种问题,它相当于一个公共仓库,保存着所有组件都能共用的数据。

1.Vuex的状态存储是响应式的,当Vue组件从store中获取状态的时候,若store中的状态发生变化,那么相应的组件也会相应地得到高效的更新

2.你不能直接改变store中的状态。改变store中的状态的唯一途径就是提交(commit) mutation。这样使得我们可以方便的跟踪每一个状态的变化。

Vuex有五个核心概念:

state   getters   mutations   actions    modules

 1.state: vuex的基本数据。用来存储变量

 2.getter:从基本数据(state)派生的数据(依赖state得到新的数据)相当于state的计算属性

 3.mutation: 提交更新数据的方法,必须是同步的(如果需要异步使用action)

 4.action: 和mutation的功能大致相同,不同之处在于------->action提交的是mutation,而不是直接变更状态,action可以包含任意异步操作 ,action中的方法默认的就是异步,并且返回promise

 5.modules:模块化vuex,可以让 每一个模块拥有自己的state, mutaion,action,getters,使得结构非常清晰,方便管理

步骤:

1.使用 npm install vuex --save 安装vuex

2. 在项目中建立一个store文件夹

3.在main.js文件中引入store中的index.js,同时在vue中注册store

4.在store文件夹中的index.js文件中引入vuex,通过 Vue.use() 来安装 Vuex。

并把modules文件夹中的各个文件引入,完善new Vuex.Stroe中的modules对象.

 5.在modules 中的每个js文件中定义自己模块的state, mutaion,action,getters。

6.在组件中获取store中某个文件中的state中的属性

语法就是:this.$store.state.注册在modules对象中的属性名.该文件state中的属性

这个是获取secretKey.js文件中的state中的secretKey属性

7.触发store中的方法

语法就是:this.$store.dispatch('注册在modules对象中的属性名/该文件中的方法名')

这个是执行secretKey.js文件中的action中的changeKey方法

再来看个例子:

再看一下app.js文件的内容:

总结一下:mutations 和 actions 中的函数入参

1.mutations中的函数接受两个参数,分别时state和传入的额外参数,这个额外的参数可以是基本类型也可以是一个对象

 

 2.Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,context可以理解为它是整个Store的对象.类似于this.$store它里面包含了state,getter,mutations,actions

因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

 实践中,我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit 很多次的时候)这时函数接受两个参数{commit, state} 和额外传入参数data(可以是基本类型也可以是对象)

 

总结一下:Vuex的辅助函数mapState, mapAction, mapMutations的用法

1. mapState 辅助函数(定义在computed中)

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: { //存放状态
    nickname:'Simba',
    age:20,
    gender:''
  },
  mutations: {},
  actions: {},
  modules: {}
})

有了vuex,我们不必在考虑组件之间的传值,直接就可以通过$store来获取不同的数据,但是如果需要vuex中的多个数据的这时候,这样写就太啰嗦了,我们可以将它定义在computed中。

Propsmethods,datacomputed的初始化都是在beforeCreatedcreated之间完成的。

<template>
  <div class="home">
    {{nickname}}
  </div>
</template>
<script>
export default {
  name: 'home',
  computed:{
    nickname(){
      return this.$store.state.nickname
    }
  }
}
</script>

但是computed中定义的代码还是很多,而这时候vuex又给我们提供了更简便的方法mapState方法

import {mapState} from 'vuex'
export default {
  name: 'home',
  computed: mapState(['nickname','age','gender'])//映射哪些字段就填入哪些字段  映射过来的字段直接可以用this.xx(字段名)使用
}

记住:用mapState等这种辅助函数的时候,前面的方法名和获取的属性名是一致的。

如果我们需要自定义一个计算属性怎么办呢?怎么添加呢?

毕竟现在已经成这样了 computed: mapState(['nickname','age','gender'])

这时候我们就需要es6中的展开运算符:...

computed: { 
  value(){
   return this.listData
},
  ...mapState(['nickname','age','gender'])
}

二、mapGetters 辅助函数 (定义在computed中)

getters相当于vue中的计算属性,通过getters进一步处理,得到我们想要的值,而且允许传参,第一个参数就是state

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
 
export default new Vuex.Store({
  state: { //存放变量
    nickname:'Simba',
    firstname:'',
    lastname:'三丰',
    age:20,
    gender:'',
    money:1000
  },
  getters:{
    realname(state){
      return state.firstname+state.lastname
    },
    money_us(state){
      return (state.money/7).toFixed(2)
    }
  },
  mutations: {},
  actions: {},
  modules: {}
})
computed: {
 valued(){
   return this.value/7
 },
 ...mapGetters(['realname','money_us'])
}

3.mapMutations辅助函数(定义在methods中)

mutations需要通过commit来调用其里面的方法,它也可以传入参数,第一个参数是state,第二个参数是载荷(payLoad),也就是额外的参数

mutations: { //类似于methods
  addAge(state,payLoad){
     state.age+=payLoad.number
  }
}

 

//  js部分
methods:{
 test(){
   this.$store.commit('addAge',{
     number:5
   })
 }
}

调用的时候第二个参数最好写成对象形式,这样我们就可以传递更多信息。

但是,这样写还是会遇到同样的问题,就是如果需要操作多个数据,就会变的麻烦,这时候我们就需要mapMutations,通过它将方法映射过来,映射过来的方法直接可以用this.xx(方法名)使用

methods:{
 ...mapMutations(['addAge'])
}
参数我们可以在调用这个方法的时候写入
<button @click="addAge({number:5})">测试</button>

4.mapActions辅助函数(定义在methods中)

actions: {
  getUserInfo(){
    return {
      nickname:'Simba',
      age:20
    }
  }
}

methods:{
  ...mapActions(['getUserInfo'])
}

mapActions(['getUserInfo']) 相当于以下代码

getUserInfo(){
  return this.$store.dispatch(‘getUserInfo’)
}

 补充:使用常量替代Mutation事件类型

把原本的方法名称由字符串转变成常量

 优点是:不容易写错,字符串容易写错,而且字符串写错以后不会报错位置,而用常量替代,如果写错,eslint可以提示错误位置

mutations: { //类似于methods
     [ADD_AGE](state,payLoad){  
         state.age+=payLoad.number
     }
  }
//将addAge方法名字定义为一个常量,当调用的时候直接引入
import {ADD_AGE} from '../store'
import {mapMutations} from 'vuex'
export default {
  methods:{
    ...mapMutations([ADD_AGE])
  }
}

 数据持久化:

vuex里面存放的数据,页面一经刷新就会丢失

解决方法:

1.存放在localStorage或者sessionStorage里面,进入页面时判断是否丢失,丢失再去localSorage或者sessionStorage里面取。

2.在app.vue根组件的created里面判断是否丢失,在进行上面的操作

3.使用vuex-persistedstate插件

npm install vuex-persistedstate

之后在store文件夹中的index.js文件中引入

import persistedState from 'vuex-persistedstate'
export default new Vuex.Store({
  getters,
  state,
  actions,
  mutations,
  plugins: [persistedState()]
})

 看一下项目中的vuex-persistedstate使用,并且把vuex存储在了sessionStorage里面了:

 

 最后再来一个补充:mutation里面只有同步函数,action可以执行异步函数,看看在项目中的具体实现:

推荐阅读