使用 Nuxt.js 时动态 Vuex 模块初始化的最佳方法是什么?
What is the best approach in dynamic Vuex module initialisation when using Nuxt.js?
最近,我一直在构建一个使用大量独立 Vuex 模块的大型应用程序。让我们看一下其中的一个(例如 support-chat
)。支持聊天位于它自己的单独页面上,在初始应用程序加载时用这个模块污染商店是多余的。我的目标是在加载页面时动态注册此模块。所以我的问题是 – 我应该在哪里、何时以及如何注册该模块?
我最终在页面组件的 beforeCreate
挂钩中注册了这个模块:
import supportChatModule from '@/vuex/modules/support-chat'
// ...
beforeCreate() {
this.$store.registerModule('support-chat', supportChatModule, { preserveState: process.client })
},
beforeDestroy() {
this.$store.unregisterModule('support-chat')
}
// ...
这种方法有什么缺陷?
如果您能分享解决该问题的方法,那就太好了。
这个问题我纠结了很久。我终于想出了一个独特的方法。
我通过在 beforeEach
方法中将每个页面的 register
和 unregister
模块移动到 router file
(我项目中的 router/index.js
)并添加所需的模块来做到这一点每个 path
.
- 页面之间共享部分模块,解决了这个问题。
- 有些模块从服务器接收到大量数据,这比留在客户端更好,以避免再次接收这些数据。我用冰箱做了这个。
这个方法可以改进。
router/index.js
router.beforeEach((to, from, next) => {
// unregister modules
if (from.meta.modules) {
for (const key in from.meta.modules.primary) {
if (to.meta.modules && to.meta.modules.primary.hasOwnProperty(key)) {
continue;
}
if (store.state.hasOwnProperty(key)) {
// don't unregister freeze modules
if (from.meta.modules.hasOwnProperty('freeze') && from.meta.modules.freeze.find(item => item == key)) {
continue;
}
store.unregisterModule(key);
}
}
}
// register modules
if (to.meta.modules) {
for (const key in to.meta.modules.primary) {
const module = to.meta.modules.primary[key]();
if (!store.state.hasOwnProperty(key)) {
store.registerModule(key, module.default);
}
}
}
});
我的路径是这样的:
{
path: 'users',
name: 'users',
meta: {
modules: {
primary: {
user: () => require('@/store/modules/moduleUser')
}
},
},
component: () => import('../views/users.vue')
},
{
path: 'foods',
name: 'foods',
meta: {
modules: {
primary: {
food: () => require('@/store/modules/moduleFood'),
user: () => require('@/store/modules/moduleUser')
},
freeze: ['food']
},
},
component: () => import('../views/foods.vue')
},
Step 1:
创建一个mixin,我命名为register-vuex-module.js
:
export const registerVuexModule = (name, module) => ({
beforeCreate() {
const { $store } = this
if ($store.hasModule(name)) $store.commit(`${name}/resetState`)
else $store.registerModule(name, module().default)
}
})
Step 2:
Use the mixin to import a module:
<template>
...
</template>
<script>
// Mixins
import { registerVuexModule } from '@/mixins/register-vuex-module'
export default {
mixins: [registerVuexModule('module-name', () => require('./vuex/MyVuexModule.js'))],
}
</script>
Step 3:
确保你的 Vuex 模块有一个 resetState
突变,并且状态从函数返回。下面是 MyVuexModule.js
的示例:
const initialState = () => ({
count: null
})
export default {
namespaced: true,
state: initialState(),
mutations: {
// ...
resetState: state => Object.assign(state, initialState())
}
}
最近,我一直在构建一个使用大量独立 Vuex 模块的大型应用程序。让我们看一下其中的一个(例如 support-chat
)。支持聊天位于它自己的单独页面上,在初始应用程序加载时用这个模块污染商店是多余的。我的目标是在加载页面时动态注册此模块。所以我的问题是 – 我应该在哪里、何时以及如何注册该模块?
我最终在页面组件的 beforeCreate
挂钩中注册了这个模块:
import supportChatModule from '@/vuex/modules/support-chat'
// ...
beforeCreate() {
this.$store.registerModule('support-chat', supportChatModule, { preserveState: process.client })
},
beforeDestroy() {
this.$store.unregisterModule('support-chat')
}
// ...
这种方法有什么缺陷?
如果您能分享解决该问题的方法,那就太好了。
这个问题我纠结了很久。我终于想出了一个独特的方法。
我通过在 beforeEach
方法中将每个页面的 register
和 unregister
模块移动到 router file
(我项目中的 router/index.js
)并添加所需的模块来做到这一点每个 path
.
- 页面之间共享部分模块,解决了这个问题。
- 有些模块从服务器接收到大量数据,这比留在客户端更好,以避免再次接收这些数据。我用冰箱做了这个。
这个方法可以改进。
router/index.js
router.beforeEach((to, from, next) => {
// unregister modules
if (from.meta.modules) {
for (const key in from.meta.modules.primary) {
if (to.meta.modules && to.meta.modules.primary.hasOwnProperty(key)) {
continue;
}
if (store.state.hasOwnProperty(key)) {
// don't unregister freeze modules
if (from.meta.modules.hasOwnProperty('freeze') && from.meta.modules.freeze.find(item => item == key)) {
continue;
}
store.unregisterModule(key);
}
}
}
// register modules
if (to.meta.modules) {
for (const key in to.meta.modules.primary) {
const module = to.meta.modules.primary[key]();
if (!store.state.hasOwnProperty(key)) {
store.registerModule(key, module.default);
}
}
}
});
我的路径是这样的:
{
path: 'users',
name: 'users',
meta: {
modules: {
primary: {
user: () => require('@/store/modules/moduleUser')
}
},
},
component: () => import('../views/users.vue')
},
{
path: 'foods',
name: 'foods',
meta: {
modules: {
primary: {
food: () => require('@/store/modules/moduleFood'),
user: () => require('@/store/modules/moduleUser')
},
freeze: ['food']
},
},
component: () => import('../views/foods.vue')
},
Step 1:
创建一个mixin,我命名为register-vuex-module.js
:
export const registerVuexModule = (name, module) => ({
beforeCreate() {
const { $store } = this
if ($store.hasModule(name)) $store.commit(`${name}/resetState`)
else $store.registerModule(name, module().default)
}
})
Step 2: Use the mixin to import a module:
<template>
...
</template>
<script>
// Mixins
import { registerVuexModule } from '@/mixins/register-vuex-module'
export default {
mixins: [registerVuexModule('module-name', () => require('./vuex/MyVuexModule.js'))],
}
</script>
Step 3:
确保你的 Vuex 模块有一个 resetState
突变,并且状态从函数返回。下面是 MyVuexModule.js
的示例:
const initialState = () => ({
count: null
})
export default {
namespaced: true,
state: initialState(),
mutations: {
// ...
resetState: state => Object.assign(state, initialState())
}
}