美文网首页
Vue状态管理 Vuex

Vue状态管理 Vuex

作者: Promi5e | 来源:发表于2019-08-26 16:11 被阅读0次

    前 言

    刚接触Vue的时候,组件之间通信真的是个令人头疼的事情,最开始还用过bus,后来知道有个Vuex这个东东,越来越喜欢,今天就做个整理。

    正 文

    • state
      都叫状态管理了,首先肯定得有状态state
    const state = {
      loginState: false
      ...
    }
    

    他就是一个简单的对象,key-value,然后我们要做的就是对这些状态进行操作(修改和读取)。

    • getters
    const getters = {
      getLoginState({ loginState }) {
        return loginState
      }
    }
    

    顾名思义,就是获取对应的state,使用方法为:

    let loginState = store.getters['getLoginState']
    
    • mutations
    const mutations = {
      setLoginState(state, { loginState }) {
        state.loginState = loginState
      }
    }
    

    mutation意思为“改变”,就是改变state的值,通过commit来实现:

    store.commit('setLoginState', { loginState: true })
    
    • actions
    const actions = {
        changeState({ commit }, payload) {
          commit('setLoginState', payload)
        }
      }
    

    action意为“动作,行为”,它有以下规则:

    1. action不可以直接修改状态state,它通过commit mutation来间接的改变state
    2. action可以包含异步操作
      使用dispatch来调用action
    store.dispatch('changeState', { loginState: true })
    
    • modules
      随着项目越来越庞大,store可能会越来越臃肿,所以Vuex提供了modules方便管理,可以根据具体业务来划分模块。
      如果loginlogout都有一个stateuserId,那么此时就需要一个namespaced属性来区别这个userId到底属于哪个模块:
    const login = {
      state: { ... },
      getters: { ... },
      mutations: { ... },
      actions: { ... },
      namespaced: true
    }
    
    const logout = {
      state: { ... },
      getters: { ... },
      mutations: { ... },
      actions: { ... },
      namespaced: true
    }
    
    const store = new Vuex.Store({
      modules: {
        login,
        logout
      }
    })
    // getters和commit时,加上模块名
    store.getters['login/userId']
    store.commit('login/userId', 123456)
    

    进阶

    有时候我们多次从store拿数据时,会觉得很繁琐,别担心,vuex提供了辅助函数,即mapState,mapGetters,mapMutations以及mapActions。使用前需要引入它们:

    import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
    
    • mapState,mapGetters
    // mapState
    mapState(['loginState'])
    // 等价于
    loginState() {
      return this.$store.state['loginState']
    }
    
    // mapGetters
    mapGetters(['loginState'])
    // 等价于
    loginState() {
      return this.$store.getters['loginState']
    }
    

    这样我们就可以结合computed使用了

    computed: {
      mapState(['loginState'])
    }
    // 获取多个状态
    computed: {
      ...mapState([
        'loginState',
        'loginInfo'
      ])
    }
    
    • mapMutations
    methods: {
      ...mapMutations([
        'setLoginState'
      ])
    }
    // 等价于
    methods: {
      setLoginState(payload) {
        this.$store.commit('setLoginState', payload)
      }
    }
    
    • mapActions
    methods: {
      ...mapActions([
        'changeState'
      ])
    }
    // 等价于
    methods: {
      changeState(payload) {
        this.$store.dispatch('changeState', payload)
      }
    }
    

    *需要注意的是,以数组为辅助函数的参数时,数组参数的每个成员必须和store中定义好的名称一一对应;如需使用别名,请使用对象参数,对象的key为我们设置的别名,value对应state里的变量名,如下:

    computed: {
      ...mapState({
        'state': 'loginState'
      })
    }
    // 等价于
    computed: {
      state() {
        return this.$store.getters['loginState']
      }
    }
    

    应用场景

    其实Vuex的应用场景还是很多的,这里简单举个例子。

    data () {
        return {
          isHorizontal: this.$store.getters[NS.MAIN.GET_IS_HORIZONTAL]
        }
      },
    
    computed: {
        isHorizontal () {
          return this.$store.getters[NS.MAIN.GET_IS_HORIZONTAL]
        }
      }
    

    这里是直接使用在了datacomputed里。

    在ts项目里,可以结合classget方法使用,效果很好

    export default class Demo extends Vue {
      name: string = 'Demo'
    
      type: string = this.$store.getters['getType']
      get number(): number {
        return this.$store.getters['getNumber']
      }
    
      mounted() {
        console.log(this.type, this.number) // default type, default number
        this.$store.commit('setType', 'new type')
        this.$store.commit('setNumber', 1)
        console.log(this.type, this.number) // default type, 1
      }
    }
    

    另外还涉及到浅拷贝的问题,看例子:

    export default class Demo extends Vue {
      name: string = 'Demo'
    
      mounted() {
        let obj = this.$store.getters['getObj'] // {success: true}
        obj.success = false
        console.log(this.$store.getters['getObj']) // {success: false}
      }
    }
    

    相关文章

      网友评论

          本文标题:Vue状态管理 Vuex

          本文链接:https://www.haomeiwen.com/subject/ovorectx.html