import { createRouter, createWebHashHistory } from "vue-router";
import { defineAsyncComponent } from "vue";
import type { Component } from "vue";
import type { RouteRecordRaw } from "vue-router";
import { fallbackUserRoute, userMenu } from "./userMenu";
import type { UserNavItem } from "./types";

const pageComponents: Record<string, Component> = {
    profile: defineAsyncComponent(() => import("./pages/ProfilePage.vue")),
    security: defineAsyncComponent(() => import("./pages/SecurityPage.vue")),
    authorizations: defineAsyncComponent(
        () => import("./pages/AuthorizationsPage.vue"),
    ),
    sessions: defineAsyncComponent(() => import("./pages/SessionsPage.vue")),
    articles: defineAsyncComponent(() => import("./pages/ArticlesPage.vue")),
    mumbles: defineAsyncComponent(() => import("./pages/MumblesPage.vue")),
    timelines: defineAsyncComponent(() => import("./pages/TimelinesPage.vue")),
    albums: defineAsyncComponent(() => import("./pages/AlbumsPage.vue")),
};

const viewlessComponent: Component = { render: () => null };

const contentEditorChildren: Record<string, RouteRecordRaw[]> = {
    articles: [
        { path: "create", name: "articles-create", component: viewlessComponent },
        {
            path: "edit/:id",
            name: "articles-edit",
            component: viewlessComponent,
        },
    ],
    mumbles: [
        { path: "create", name: "mumbles-create", component: viewlessComponent },
        {
            path: "edit/:id",
            name: "mumbles-edit",
            component: viewlessComponent,
        },
    ],
    timelines: [
        { path: "create", name: "timelines-create", component: viewlessComponent },
        {
            path: "edit/:id",
            name: "timelines-edit",
            component: viewlessComponent,
        },
    ],
    albums: [
        { path: "create", name: "albums-create", component: viewlessComponent },
        { path: "edit/:id", name: "albums-edit", component: viewlessComponent },
    ],
};

function menuRoute(item: UserNavItem): RouteRecordRaw {
    return {
        path: item.hash.replace(/^#/, ""),
        name: item.key,
        component: pageComponents[item.key],
        meta: {
            key: item.key,
            icon: item.icon,
            title: item.title,
            subtitle: item.subtitle,
            group: item.group,
            accent: item.accent,
        },
        children: contentEditorChildren[item.key],
    };
}

export const userRouter = createRouter({
    history: createWebHashHistory(),
    routes: [
        ...userMenu.map(menuRoute),
        { path: "/:pathMatch(.*)*", redirect: `/${fallbackUserRoute.key}` },
    ],
});
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

代码解释

这是一个 Vue 3 + Vue Router 的路由配置文件,用于构建用户中心相关的路由系统。

核心功能模块

1. 页面组件映射 (pageComponents)

const pageComponents: Record<string, Component> = { ... }
  • 使用 defineAsyncComponent 实现懒加载,优化首屏加载性能
  • 包含 8 个用户中心页面:
    • 个人资料 (profile)
    • 安全设置 (security)
    • 授权管理 (authorizations)
    • 会话管理 (sessions)
    • 文章 (articles)
    • 动态 (mumbles)
    • 时间线 (timelines)
    • 相册 (albums)

2. 无视图组件 (viewlessComponent)

const viewlessComponent: Component = { render: () => null }
  • 渲染空内容的占位组件
  • 用于需要路由但不需要独立视图的场景(如弹窗编辑)

3. 内容编辑器子路由 (contentEditorChildren)

为 4 类内容(articles/mumbles/timelines/albums)配置统一的增删改查路由:

  • 创建路由: /create
  • 编辑路由: /edit/:id (带动态参数)

使用 viewlessComponent 说明编辑操作可能通过模态框或侧边栏实现,而非独立页面。

function menuRoute(item: UserNavItem): RouteRecordRaw
  • 将导航菜单项转换为路由配置
  • 自动关联:
    • 路径处理:去除 hash 前缀 #
    • 组件绑定:从 pageComponents 匹配
    • 元数据传递:保留菜单的 icon/title/subtitle 等信息
    • 子路由注入:自动挂载对应的编辑器子路由

5. 路由实例创建 (userRouter)

export const userRouter = createRouter({ ... })
  • 使用 Hash 模式 (createWebHashHistory),兼容性更好,无需服务器配置
  • 路由配置包括:
    • 动态生成的菜单路由(通过 userMenu.map(menuRoute))
    • 全局 404 重定向到默认页面 (fallbackUserRoute)

技术亮点

  1. 类型安全:完整的 TypeScript 类型标注
  2. 按需加载:所有页面组件均异步加载
  3. 元数据驱动:路由配置完全由导航菜单数据驱动
  4. 扩展性强:新增内容类型只需在 3 个映射表中添加配置
  5. 路由守卫友好:meta 中保留完整的菜单信息,方便实现权限控制

典型使用场景

  • 用户点击"文章"菜单 → 跳转到 /articles
  • 点击"新建文章" → 跳转到 /articles/create → 触发模态框显示编辑器
  • 点击"编辑" → 跳转到 /articles/edit/123 → 加载指定文章内容到编辑器
评论加载中...