如何为生产应用程序构建大规模 Vuex 存储

2025-05-25

如何为生产应用程序构建大规模 Vuex 存储

查看 Vuex 教程时,您会发现其中大多数都非常简单。

逻辑解释得很好,但可扩展性不佳。这在我的生产应用中该如何实现?

以下是Vuex 官方文档中的一个简单存储示例:



import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})


Enter fullscreen mode Exit fullscreen mode
一个简单的商店

这个无需解释。我假设你在阅读本文之前已经具备一些 Vue 和 Vuex 的知识。

我的目标不是解释什么是商店、状态或突变。

相反,我想向您展示一个拥有 1,000 多个状态属性、突变、动作和 getter 的大型商店。

我想教你如何构建商店以实现最佳的可维护性、可读性和可重用性。

它可以有 100,000 多个属性。它仍然清晰。

让我们开始吧。

认识模块

正如我们之前所说,把所有内容放在一个文件中会造成混乱。你肯定不想看到一个超过 50,000 行代码的文件。这就像把你的应用程序放在一个组件里一样。

Vuex 通过将商店划分为模块来帮助我们。

为了本示例的目的,我将创建一个包含两个模块的 store。请注意,对于 100 多个模块,以及每个模块内 100 多个 action、getter 和 mutations,此过程相同。




const userModule = {
  namespaced: true,
  state: () => ({}),
  mutations: {},
  actions: {},
  getters: {}
}

const organisationModule = {
  namespaced: true,
  state: () => ({}),
  mutations: {},
  actions: {},
}

const store = new VueX.Store({
  modules: {
    user: userModule,
    organisation: organisationModule
  }
})

store.state.user // -> `userModule`'s state
store.state.organisation // -> `organisationModule`'s state


Enter fullscreen mode Exit fullscreen mode
更新商店

这个namespaced属性在这里非常重要。如果没有它,action、mutations 和 getters 仍然会在全局命名空间中注册。

通过namespaced将属性设置为 true,我们也将动作、突变和获取器划分到模块中。

如果有两个同名的操作,这将非常有用。将它们放在全局命名空间中可能会产生冲突。



const userModule = {
  namespaced: true,
  state: () => ({}),
  mutations: {},
  actions: {
    'SET_USER'() {},
    'SET_USER_LOCATION'() {}
  },
  getters: {}
}

store.state.user['SET_USER']() // correct ✅

stote.state['SET_USER']() // wrong ❌


Enter fullscreen mode Exit fullscreen mode
命名空间模块

如你所见,该模块现在完全是“本地”的。我们只能通过 state 上的 user 对象来访问它。

这正是我们的大规模应用程序所希望的。


太棒了,现在我们有一个分为多个模块的商店!

但是,我不喜欢操作的硬编码字符串。这绝对难以维护。让我们解决这个问题。

让你远离头痛的类型

我们不想访问每个文件的每个模块的每个属性。这句话听起来很可怕。

我们希望先导入它们。然后使用mapGettersmapActionsmapMutations来实现。



// userModule.js
export const SET_USER = 'SET_USER'
export const SET_USER_LOCATION = 'SET_USER_LOCATION'

const userModule = {
  namespaced: true,
  state: () => ({}),
  mutations: {},
  actions: {
    [SET_USER]() {},
    [SET_USER_LOCATION]() {}
  },
  getters: {}
}

// vue file
import { mapActions } from 'vuex'
import { SET_USER, SET_USER_LOCATION } from './userModule.js'

...mapActions({
  setUser: SET_USER,
  setUserLocation: SET_USER_LOCATION
})


Enter fullscreen mode Exit fullscreen mode
使用 mapActions 访问操作

这使您可以清楚地查看 Vue 文件使用的商店属性。

但这还不够。所有内容仍然在一个文件中。让我们看看如何才能正确地缩放它。

文件夹结构

理想情况下,我们希望将模块拆分到不同的文件夹中。在这些模块中,我们希望将它们的变更、操作、getter、状态属性和类型拆分到不同的文件中。

所需的文件夹结构

所需的文件夹结构

文件夹store将在我们项目的根文件夹中创建。

它将包含两件事:

  1. index.js文件
  2. modules文件夹

在解释index.js文件之前,我们先来看看如何划分单个模块。我们先来检查一下user模块。

它的所有 action、mutations 和 getter 都应该列在types.js文件中。例如:



// actions
export const SET_USER = 'SET_USER'
export const SET_USER_LOCATION = 'SET_USER_LOCATION'

// mutations

// getters


Enter fullscreen mode Exit fullscreen mode
商店/模块/用户/types.js

每次我们想要使用它们时,通过导入这些 const,我们将有一个清晰的视图。

现在让我们看看操作。我们想将它们移动到actions.js文件中。

为此,我们只需要复制actions模块内的对象export default并导入类型:



import { SET_USER, SET_USER_LOCATION } from './types.js'

export default {
  [SET_USER]() {},
  [SET_USER_LOCATION]() {}
}


Enter fullscreen mode Exit fullscreen mode
商店/模块/用户/actions.js

我们将对突变和获取器执行相同的操作。状态属性将保留在index.js(用户模块文件夹中):



import actions from './actions.js'
import mutations from './mutations.js'
import getters from './getters.js'

const state = {}

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


Enter fullscreen mode Exit fullscreen mode
商店/模块/用户/index.js

现在我们已将所有模块分成多个文件。

index.js剩下的一件事就是链接文件夹内文件中的所有模块store



import Vue from 'vue'
import Vuex from 'vuex'

// Modules import
import UserModule from 'modules/user'
import OrganisationModule from 'modules/organisation'

Vue.use(Vuex)

const state = {}
const actions = ({})
const mutations = ({})
const getters = ({})

const modules = {
  user: userModule,
  organisation: organisationModule
}

export default new Vuex.Store({
  state,
  actions,
  mutations,
  getters,
  modules
})


Enter fullscreen mode Exit fullscreen mode
商店/index.js

结论

通过使用这种架构,我们的大规模生产应用程序的可扩展性没有任何问题。

一切都很容易找到。

我们确切地知道所有动作在哪里被触发。

该系统具有高度的可维护性。

如果您对改进有任何建议,请告诉我。我很乐意听取您的意见。

文章来源:https://dev.to/domagojvidovic/how-to-struct-a-massive-vuex-store-for-a-production-app-97a
PREV
了解如何在 .Net Core 3.0 中构建您的第一个 Blazor WebAssembly 应用程序
NEXT
前 5 个 MERN STACK 项目可提高你的实践理解🚀