vuex状态管理

一、vuex是什么?

官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

我们知道,在vue的组件化开发中,经常会遇到需要将当前组件的状态传递给其他组件。

然而组件通信有两种:

  • 父组件 ---> 子组件通信使用:props
  • 子组件 ---> 父组件通信使用:$emit

但当通信双方不是父子组件甚至压根不存在相关联系,或者一个状态需要共享给多个组件时,就会非常麻烦,数据也会很难维护,这对我们开发来讲就很不友好。这时候就需要使用vuex。

二、vuex的组成

vuex 包含有五个基本的对象:

  • state:存储状态。也就是变量;
  • getters:派生状态。也就是set、get中的get,有两个可选参数:state、getters分别可以获取state中的变量和其他的getters。外部调用方式:store.getters.personInfo()。就和vue的computed差不多;
  • mutations:提交状态修改。也就是set、get中的set,这是vuex中唯一修改state的方式,但不支持异步操作。第一个参数默认是state。外部调用方式:store.commit('SET_AGE', 18)。和vue中的methods类似。
  • actions:和mutations类似。不过actions支持异步操作。第一个参数默认是和store具有相同参数属性的对象。外部调用方式:store.dispatch('nameAsyn')
  • modules:store的子模块,内容就相当于是store的一个实例。调用方式和前面介绍的相似,只是要加上当前子模块名,如:store.a.getters.xxx()

state

在state中定义共享状态

//state.js
export default state = {
    count: 0
}

获取state的值,需要放在计算属性中,保证每次state能够响应式的获取

computed:{
    count(){
        return this.$stores.state.count //获取值
    }
}

这种获取方式是比较繁琐的,因此vuex给我们提供了mapState,便于我们简洁性的获取值

import { mapState } from 'vuex'
export default{
    computed:{
        ...mapState(['count']) //这样我们在组件就可以通过this.count获取对应的值了
    }
}

getters

state的派生状态值,可以理解成是store的计算属性,它一般是一个方法,方法接受一个参数state。

//getter.js
export default {
    getCount: state => state.count + 1
}

它的辅助函数是mapGetter,一般也放在computed里

import { mapGetters } from 'vuex'
export default {
  computed: {
   // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters(['getCount'])
  }
}

mutations

vuex规定更改state的值唯一方法是提交 mutation,原因是为了能够明确的追踪状态的变化,它接受2个参数(state,newVal),第二个参数可以是字符串也可以是对象

//mutations.js
export default {
    setCount(state,newVal){
        state.count = newVal
    }
}

必须通过commit的方法触发调用它

this.$store.commit('setCount',20) //此时你把state中的count的值变成了20

它的辅助函数是mapMutations,它一般放在methods中

import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations(['setCount'])
  }
}

在 Vuex 中,mutation 都是同步事务,不可写入异步操作

actions

Action 类似于 mutation,它主要用于:

  • 批量的同步操作
  • 异步操作

它接受一个store 实例具有相同方法和属性的 context对象,注意它提交的是 mutation,而不是直接变更状态

//actions.js
export default {
    increment(context){
        context.commit('setCount')
    }
}

在实践中可以通过参数解构的方法简化代码

increment({commit}){
    commit('setCount')
}

在组件中通过分发dispatch的方法来触发action

    
this.$store.dispatch('increment')

这样做的目的是为了可以在action的内部执行异步操作(比如通过接口请求后才更改state的值)

increment({commit}){
    setTimeout(()=>{
        commit('setCount')
    },1000)
}

也可以同步批量更改state中的值

increment({commit}){
    commit('mutation1')
    commit('mutation2')
    commit('mutation3')
}

它的辅助函数是mapActions,一般放在methods中

import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(['increment']) //将 this.increment() 映射为 this.$store.dispatch('increment')
  }
}

action的返回接收,可以返回一个Promise

export default{
    actionA ({ commit }) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                commit('someMutation')
                resolve()
            }, 1000)
        })
    }
}

数据接受后处理

this.$store.dispatch('actionA').then(() => {
  // ...
})

三、vuex搭建目录

我们一般会在src目录下建立一个名为store的文件夹专门放vuex的文件,目录里存放如下:

├── index.html
├── main.js
├── components
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── state.js          # 跟级别的 state
    ├── getters.js        # 跟级别的 getter
    ├── mutation-types.js # 根级别的mutations名称(官方推荐mutions方法名使用大写)
    ├── mutations.js      # 根级别的 mutation
    ├── actions.js        # 根级别的 action
    └── modules
        ├── m1.js         # 模块1
        └── m2.js         # 模块2

ingdex.js导出store如下

import Vue from 'vue'
import VueX from 'vuex'
import States from './state'
import Getters from './getters'
import Mutations from './mutations'
import Actions from './actions'
Vue.use(Vuex)
export default nex Vuex.Store({
    State,
    Getters,
    Mutations,
    Actions
})

然后在根目录下的main.js中全局引入

import store from './store'
new Vue({
  el: '#app',
  router,
  store, //在这里
  template: '<App/>',
  components: {
    App
  }
})

三、总结

自己也是边了解边使用,使用几次似乎没那么难理解。。。。。

posted @ 2018-09-01 18:26  c'estlavie  阅读(228)  评论(0编辑  收藏  举报