vuex的使用

2019-12-25  本文已影响0人  青争小台

1.模块化使用时

模块内:

//方法一:使用export default统一抛出
const user = {
  state: {
    admins_info: ''
  },
  mutations: {
    SET_ADMINS(state, admins) {
      state.admins_info = admins
    }
  },
  actions: {
    SET_ADMINS(context, admins) {
      context.commit('SET_ADMINS', admins)
    }
  }
}
export default user


//方法二:使用export单个抛出
const state = {
  admins: ''
}
const mutations = {
  SET_ADMINS: (state, admins) => {
    state.admins = admins
  }
}
const actions = {
  SET_ADMINS(context, admins) {
   context.commit('SET_ADMINS', admins)
  }
}
export default {
  //成为一个带命名空间的模块
  namespaced: true,
  state,
  mutations,
  actions
}

getter,mutation,action 他们默认都是注册在全局命名空间的,所以我们默认是可以和使用根状态一样去使用他们,但是这样不可避免会出现命名冲突的问题,所以使模块有更高的封装性与复用性,我们可以通过添加 namespaced: true 使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

页面使用:

import { auth } from '@/api/login'
import { mapState } from 'vuex'

export default {
  name: 'Login',
  data() {
    return {}
  },
  methods: {
    login(){
      auth().then(response => {
        //当使用方法一导出时
        this.$store.dispatch('SET_ADMINS', response.data})
        //当使用方法二导出时
        this.$store.dispatch('user/SET_ADMINS', response.data})
      })
    }
  },
  computed: {
    //当使用方法一导出时
    ...mapState({
      admins_info: state => state.user.admins_info
    })
    //当使用方法二导出时,也可以用上面那个方法
    ...mapState('user', {
      admins_info: state => state.admins_info
    })
  }
}

store 里

// import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
import settings from './modules/settings'
import user from './modules/user'
// import createPersistedState from 'vuex-persistedstate'  vuex的持久化存储
import VuexPersistence from 'vuex-persist'  //vuex的持久化存储

// Vue.use(Vuex)
const vuexLocal = new VuexPersistence({
  storage: window.localStorage
})
const store = new Vuex.Store({
  modules: {
    app,
    settings,
    user
  },
  getters,
  plugins: [vuexLocal.plugin]  //vuex的持久化存储
  // plugins: [VuexPersistence()]----vuex的持久化存储
})

export default store

2.辅助函数

//当是将vuex模块化时,有三个模块app,user,setting,此时需要在state后加上模块名,action需要加上空间名
...mapState({
       admins_info: state => state.user.admins_info.admins,
       sidebar: state => state.app.sidebar,
       device: state => state.app.device,
       fixedHeader: state => state.settings.fixedHeader
    })

...mapActions({'closeSideBar':'app/closeSideBar',SET_ADMINS:'user/SET_ADMINS'}),
this.closeSideBar({ withoutAnimation: false })//调用action



//当没有模块化时,直接state就行
  ...mapState({
    add: state => state.add,
    counts: state => state.counts
  })
  

//当没有模块化时,并且赋值前后属性名一样时(...mapState,...mapGetters,...mapActions),可以简写成如下:
  ...mapState([
    'add',
    'counts'
  ])
...mapGetters(['filteredList'])
...mapActions(['closeSideBar']),


//...mapState,处理后的state数据
...mapState({
      admins_info: state => state.user.admins_info.admins,
      NO(state) {
        return {no:state.user.admins_info.admins.no}
      }
    })
// getter
this.$store.getters['moduleB/bFullName']; 

...mapGetters({
  bGetter2: 'moduleB/bFullName'
})


// mutation 
this.$store.commit('moduleB/SET_B_NAME', {
  name: 'QQ'
});

...mapMutations({
  setBname: 'moduleB/SET_B_NAME'
}),


// action
this.$store.dispatch('moduleB/ASYNC_SET_NAME', { name: "JJ" });

...mapActions({
  aSetAge: 'moduleB/ASYNC_SET_NAME',
}),

每次都要写模块名,这样写下来很烦,所以这些辅助函数给我们提供了一个参数位来绑定命名空间。

// moduleB 模块内的 bName
...mapState('moduleB', {
  name: state => state.bName
})

// 同理 mapAction mapMutation 也可以这个样子
...mapAction('moduleB',[
  '/ASYNC_SET_NAME'
])

除了这个之外,如果你当前组件用的 vuex 状态都是一个模块的话,我们可以使用 createNamespacedHelpers 创建基于某个命名空间辅助函数,如下:

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('moduleB') // moduleName

这样创建之后,我们就可以用之前的写法来访问到模块的状态。

...mapState({
  bName: state => state.bName,
}),

3.在带命名空间的模块内访问全局内容

如果你希望使用全局 state 和 getter,rootState 和 rootGetter 会作为第三和第四参数传入 getter,也会通过 context 对象的属性传入 action。

若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。具体看下面代码:

modules: {
  foo: {
    namespaced: true,

    getters: {
      // 在这个模块的 getter 中,`getters` 被局部化了
      // 你可以使用 getter 的第四个参数来调用 `rootGetters`
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter 模块内的 getter'
        rootGetters.someOtherGetter // -> 'someOtherGetter 全局的getter'
      },
      someOtherGetter: state => { ... }
    },

    actions: {
      // 在这个模块中, dispatch 和 commit 也被局部化了
      // 他们可以接受 `root` 属性以访问根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction' 模块内的 action
        dispatch('someOtherAction', null, { root: true }) // ->'someOtherAction' 全局的 action 

        commit('someMutation') // -> 'foo/someMutation' 模块内的 action
        commit('someMutation', null, { root: true }) // -> 'someMutation' 全局 mutation
      },
      someOtherAction (ctx, payload) { ... }
    }
  }
}

4.将模块内的 action 注册为全局

这个感觉和维护模块的封装性有点冲突,但是既然作者提出来了,那就学吧,当我们想要我们模块内的某个 action 提升为全局 action 的时候,在他声明的时候,添加 root: true,并将 action 的定义放到 hanler 函数中,具体如下:

const actions = {
    // 模块内 action
    [ASET_AGE]({ commit }, payload) {
        setTimeout(() => {
            commit('SET_B_NAME', payload.name);
        }, 2000)
    },
    // 提升到全局的 action 
    globalAction: {
        root: true,
        handler({ commit }, payload) {
            debugger
            setTimeout(() => {
                commit('SET_B_NAME', payload.name);
            }, 2000)
        }
    }
}

部分内容来自https://segmentfault.com/a/1190000019924674

上一篇 下一篇

猜你喜欢

热点阅读