Skip to content

组件注册

在 TechUI 的工作台(Admin)体系中,组件注册 (Component Register) 是连接“后端菜单数据”与“前端 Vue 组件文件”的关键桥梁。

由于 Vite、Webpack 等构建工具对动态 import() 语句有严格的静态分析限制(通常不支持完全动态的变量路径),因此我们需要在前端维护一份注册表,显式地声明“路由标识”与“文件路径”的对应关系。

核心机制

组件注册表本质上是一个键值对对象:

  • Key (键):路由的唯一标识字符串(如 dashboard)。后端返回的菜单数据中 label 字段必须与此 Key 完全一致。
  • Value (值):一个返回 Promise 的函数,指向具体的 .vue 文件路径。

配置指南

创建组件

首先,在您的 src/viewssrc/pages 目录下开发标准的 Vue 组件。

编写注册表 (register.js)

在项目的合适位置(如 src/navigation/register.js)维护注册表文件。

javascript
import { markRaw } from "vue";

// 定义组件映射关系
const register = {
  // 键名:需与后端菜单的 label 字段一致
  // 值:组件的动态导入函数
  
  // 示例:仪表盘
  dashboard: () => import("@/views/dashboard/index.vue"),
  
  // 示例:用户管理
  userList: () => import("@/views/system/user/list.vue"),
  
  // 示例:系统设置
  setting: () => import("@/views/system/setting.vue"),
}

// 性能优化:使用 markRaw 标记
// 防止这些组件加载函数被 Vue 的响应式系统代理,减少不必要的性能开销
Object.keys(register).forEach(key => {
  register[key] = markRaw(register[key]);
});

export default register;

全局注入

在应用入口文件(如 App.vuemain.js)中,将该注册表注入到 TechUI 的全局 Admin 状态中。这一步必须在路由初始化之前完成。

javascript
// App.vue 或 main.js
import componentRegister from "./navigation/register"; // 导入上面的文件
import { inject } from "vue";

// 获取全局服务
const { $ADMIN } = inject('$global');

// 注入注册表
$ADMIN.value.componentRegister = componentRegister;

工作流程

一旦配置完成,当动态路由系统启动时,会按照以下流程工作:

  1. 获取数据:前端从后端 API 获取菜单列表,例如:
    json
    { "label": "dashboard", "title": "仪表盘", ... }
  2. 查找组件:动态路由逻辑读取菜单中的 label ("dashboard"),并在 $ADMIN.componentRegister 中查找对应的 Key。
  3. 路由挂载:找到对应的 () => import(...) 函数后,将其作为 component 参数,通过 router.addRoute 动态添加到路由系统中。

最佳实践

  • 唯一性:确保 register.js 中的 Key 是全局唯一的。
  • 按需加载:始终使用 () => import(...) 的箭头函数形式,确保组件只有在被访问时才加载(代码分割),从而优化首屏性能。
  • 命名规范:建议 Key 的命名与文件路径或业务功能保持语义一致,方便维护。

常见问题

Q: 为什么不能直接使用后端返回的路径?A: 构建工具(Vite/Webpack)在打包时需要知道确切的文件依赖关系。如果使用完全动态的变量(如 import(serverPath)),构建工具无法确定需要打包哪些文件,会导致运行时找不到模块。使用 register.js 相当于告诉构建工具:“这些文件可能会被用到,请将它们打包”。

Q: 新增页面后显示“组件未找到”警告?A: 请检查以下两点:

  1. register.js 中是否已添加了该页面的配置。
  2. 后端返回菜单数据的 label 字段是否与 register.js 中的 Key 完全匹配(区分大小写)。