模块注册 #

静态注册 vs 动态注册 #

静态注册 #

在创建 store 时注册模块:

javascript
const store = createStore({
  modules: {
    user: userModule,
    cart: cartModule
  }
})

动态注册 #

在 store 创建后注册模块:

javascript
// 创建 store
const store = createStore({})

// 动态注册模块
store.registerModule('user', userModule)

registerModule #

基本用法 #

javascript
// 注册单个模块
store.registerModule('user', {
  state: () => ({
    name: '',
    email: ''
  }),
  mutations: {
    SET_NAME(state, name) {
      state.name = name
    }
  }
})

// 访问
store.state.user.name

嵌套模块 #

javascript
// 注册嵌套模块
store.registerModule(['user', 'profile'], {
  state: () => ({
    avatar: '',
    bio: ''
  })
})

// 访问
store.state.user.profile.avatar

保留状态 #

javascript
// 注册时保留已有状态
store.registerModule('user', userModule, {
  preserveState: true  // 保留已存在的状态
})

unregisterModule #

卸载模块 #

javascript
// 注册模块
store.registerModule('user', userModule)

// 卸载模块
store.unregisterModule('user')

// 访问会返回 undefined
store.state.user  // undefined

注意事项 #

javascript
// 不能卸载静态注册的模块
const store = createStore({
  modules: {
    user: userModule  // 静态注册
  }
})

store.unregisterModule('user')  // 无效

hasModule #

检查模块是否存在 #

javascript
// 检查模块是否已注册
if (store.hasModule('user')) {
  console.log('User module exists')
}

// 检查嵌套模块
if (store.hasModule(['user', 'profile'])) {
  console.log('User profile module exists')
}

使用场景 #

按需加载模块 #

javascript
// 路由守卫中加载模块
router.beforeEach(async (to, from, next) => {
  if (to.meta.requiresAuth && !store.hasModule('auth')) {
    // 动态加载认证模块
    const authModule = await import('./modules/auth')
    store.registerModule('auth', authModule.default)
  }
  
  next()
})

懒加载模块 #

javascript
// 组件中懒加载模块
export default {
  name: 'AdminPanel',
  
  async created() {
    if (!this.$store.hasModule('admin')) {
      const adminModule = await import('@/store/modules/admin')
      this.$store.registerModule('admin', adminModule.default)
    }
    
    this.$store.dispatch('admin/fetchDashboard')
  },
  
  beforeUnmount() {
    // 组件销毁时卸载模块
    this.$store.unregisterModule('admin')
  }
}

插件注册模块 #

javascript
// Vuex 插件
function createWebSocketPlugin(socket) {
  return store => {
    // 注册 websocket 模块
    store.registerModule('websocket', {
      state: () => ({
        connected: false,
        messages: []
      }),
      
      mutations: {
        SET_CONNECTED(state, connected) {
          state.connected = connected
        },
        ADD_MESSAGE(state, message) {
          state.messages.push(message)
        }
      }
    })
    
    // 监听 socket 事件
    socket.on('connect', () => {
      store.commit('websocket/SET_CONNECTED', true)
    })
    
    socket.on('message', (message) => {
      store.commit('websocket/ADD_MESSAGE', message)
    })
    
    socket.on('disconnect', () => {
      store.commit('websocket/SET_CONNECTED', false)
    })
  }
}

// 使用插件
const store = createStore({
  plugins: [createWebSocketPlugin(socket)]
})

多实例模块 #

javascript
// 创建可复用的模块工厂
function createFormModule(formId) {
  return {
    namespaced: true,
    
    state: () => ({
      id: formId,
      values: {},
      errors: {},
      touched: {}
    }),
    
    mutations: {
      SET_VALUE(state, { field, value }) {
        state.values[field] = value
      },
      SET_ERROR(state, { field, error }) {
        state.errors[field] = error
      },
      SET_TOUCHED(state, field) {
        state.touched[field] = true
      },
      RESET(state) {
        state.values = {}
        state.errors = {}
        state.touched = {}
      }
    }
  }
}

// 为每个表单注册独立模块
store.registerModule(['forms', 'login'], createFormModule('login'))
store.registerModule(['forms', 'register'], createFormModule('register'))

实战示例 #

动态加载功能模块 #

javascript
// store/index.js
import { createStore } from 'vuex'
import user from './modules/user'

export default createStore({
  modules: {
    user  // 核心模块静态加载
  }
})

// store/modules/loader.js
const moduleCache = new Map()

export async function loadModule(store, moduleName) {
  if (moduleCache.has(moduleName)) {
    return moduleCache.get(moduleName)
  }
  
  if (store.hasModule(moduleName)) {
    return
  }
  
  try {
    const module = await import(`./modules/${moduleName}`)
    store.registerModule(moduleName, module.default)
    moduleCache.set(moduleName, module.default)
  } catch (error) {
    console.error(`Failed to load module: ${moduleName}`, error)
    throw error
  }
}

// 使用
import { loadModule } from './modules/loader'

// 路由配置
const routes = [
  {
    path: '/dashboard',
    component: () => import('@/views/Dashboard.vue'),
    meta: { module: 'dashboard' }
  },
  {
    path: '/products',
    component: () => import('@/views/Products.vue'),
    meta: { module: 'products' }
  }
]

// 路由守卫
router.beforeEach(async (to, from, next) => {
  const moduleName = to.meta.module
  
  if (moduleName) {
    await loadModule(store, moduleName)
  }
  
  next()
})

临时模块管理 #

javascript
// composables/useTempModule.js
import { onUnmounted } from 'vue'
import { useStore } from 'vuex'

export function useTempModule(moduleName, moduleDefinition) {
  const store = useStore()
  
  // 注册模块
  if (!store.hasModule(moduleName)) {
    store.registerModule(moduleName, moduleDefinition)
  }
  
  // 组件卸载时清理
  onUnmounted(() => {
    if (store.hasModule(moduleName)) {
      store.unregisterModule(moduleName)
    }
  })
  
  return {
    state: computed(() => store.state[moduleName]),
    commit: (type, payload) => store.commit(`${moduleName}/${type}`, payload),
    dispatch: (type, payload) => store.dispatch(`${moduleName}/${type}`, payload)
  }
}

// 使用
export default {
  setup() {
    const { state, commit, dispatch } = useTempModule('tempForm', {
      namespaced: true,
      state: () => ({ data: null }),
      mutations: { SET_DATA: (s, d) => s.data = d }
    })
    
    return { state }
  }
}

条件模块注册 #

javascript
// 根据用户权限加载模块
actions: {
  async initApp({ dispatch, commit }) {
    // 获取用户权限
    const permissions = await api.getPermissions()
    commit('SET_PERMISSIONS', permissions)
    
    // 根据权限加载模块
    if (permissions.includes('admin')) {
      await dispatch('loadAdminModule')
    }
    
    if (permissions.includes('reports')) {
      await dispatch('loadReportsModule')
    }
  },
  
  async loadAdminModule({ state }) {
    if (!this.hasModule('admin')) {
      const adminModule = await import('./modules/admin')
      this.registerModule('admin', adminModule.default)
    }
  }
}

最佳实践 #

1. 模块命名规范 #

javascript
// 推荐:清晰的命名
store.registerModule('userProfile', profileModule)
store.registerModule('shoppingCart', cartModule)

// 不推荐:模糊的命名
store.registerModule('module1', someModule)

2. 检查模块是否存在 #

javascript
// 推荐:先检查再注册
if (!store.hasModule('user')) {
  store.registerModule('user', userModule)
}

// 不推荐:直接注册可能覆盖
store.registerModule('user', userModule)

3. 及时清理 #

javascript
// 推荐:不再使用时卸载
onUnmounted(() => {
  store.unregisterModule('tempModule')
})

// 不推荐:不清理导致内存泄漏

4. 错误处理 #

javascript
try {
  if (!store.hasModule(moduleName)) {
    const module = await import(`./modules/${moduleName}`)
    store.registerModule(moduleName, module.default)
  }
} catch (error) {
  console.error(`Failed to register module: ${moduleName}`, error)
  // 处理错误
}

总结 #

模块注册要点:

方法 说明
registerModule 动态注册模块
unregisterModule 卸载动态注册的模块
hasModule 检查模块是否存在
preserveState 注册时保留已有状态

继续学习 状态持久化,了解如何持久化存储状态。

最后更新:2026-03-28