VUE - Vuex/store

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex允许我们将store分割成模块(module)。每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:

 

 

一、使用了命名空间

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
import getters from './getters'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    user
  },
  getters
})

export default store

其中 getters:

const getters = {
  sidebar: state => state.app.sidebar,
  size: state => state.app.size,
  device: state => state.app.device
  token: state => state.user.token,
  avatar: state => state.user.avatar,
  name: state => state.user.name,
  introduction: state => state.user.introduction,
  roles: state => state.user.roles,
  permissions: state => state.user.permissions
}
export default getters

我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。app module 示例:

import Cookies from 'js-cookie'

const state = {
  sidebar: {
    opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
    withoutAnimation: false
  },
  device: 'desktop',
  size: Cookies.get('size') || 'medium'
}

const mutations = {
  TOGGLE_SIDEBAR: state => {
    state.sidebar.opened = !state.sidebar.opened
    state.sidebar.withoutAnimation = false
    if (state.sidebar.opened) {
      Cookies.set('sidebarStatus', 1)
    } else {
      Cookies.set('sidebarStatus', 0)
    }
  },
  CLOSE_SIDEBAR: (state, withoutAnimation) => {
    Cookies.set('sidebarStatus', 0)
    state.sidebar.opened = false
    state.sidebar.withoutAnimation = withoutAnimation
  },
  TOGGLE_DEVICE: (state, device) => {
    state.device = device
  },
  SET_SIZE: (state, size) => {
    state.size = size
    Cookies.set('size', size)
  }
}

const actions = {
  toggleSideBar({ commit }) {
    commit('TOGGLE_SIDEBAR')
  },
  closeSideBar({ commit }, { withoutAnimation }) {
    commit('CLOSE_SIDEBAR', withoutAnimation)
  },
  toggleDevice({ commit }, device) {
    commit('TOGGLE_DEVICE', device)
  },
  setSize({ commit }, size) {
    commit('SET_SIZE', size)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

一般使用action来提交更改

this.$store.dispatch('app/setSize', size)

取vuex state的时候可以直接使用:

 this.$store.state.permission.topbarRouters;

如果有getters的话,也可以通过getters来取:

this.$store.getters.permission_routes

使用vuex 提供的辅助函数 来取:

mapGetters 辅助函数是将 store 中的 getter 映射到局部计算属性:

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组;

 computed: {
        ...mapState(["settings"]),
        ...mapGetters(["sidebarRouters", "sidebar"])
}

如果你想将一个 getter 属性另取一个名字,使用对象形式:

...mapGetters({
  // 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})

 vue-devtool :

二、未使用命名空间

如果modules未使用命名空间 ,默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。则有如下规则:

组件中获取state值的时候,通过指定模块名来获取,$store.state.a.name 

组件中调用 模块的 mutations 时,和普通的调用方法一样,直接commit 名字即可,如果模块间有重名的,则都会执行,一般情况下 我们避免模块有重名的mutation;

组件中调用 模块的 getters 时,和普通的调用方法一样,直接getters 名字即可,如果模块间有重名的,则会报错,但会之心后面的getter,一般情况下,我们避免模块getters重名。

组件中调用 模块的 action 时,和普通的调用方法一样,直接dispatch名称即可,如果模块间有重名的,则都会执行,一般情况下,我们避免模块间action重名。

 三、混用

可以在一个store中同时使用命名空间、非命名空间,调用时 根据各自的规则进行调用即可。

 

参考:https://vuex.vuejs.org/zh/guide/modules.html#%E6%A8%A1%E5%9D%97%E7%9A%84%E5%B1%80%E9%83%A8%E7%8A%B6%E6%80%81

posted on 2021-12-30 11:02  TrustNature  阅读(93)  评论(0编辑  收藏  举报