elegant-router 详细介绍

elegant-router 是一个为 Vue 3 设计的优雅、类型安全的路由库,它让 Vue Router 的使用更加现代化和类型安全。

1. 是什么?

1.1 核心定位

// 传统 Vue Router
const routes = [
  { path: '/user', component: User }
] // ❌ 没有类型安全

// 使用 elegant-router
const routes = elegantRouter({
  user: route('/user', () => import('./User.vue'))
}) // ✅ 完全类型安全

2. 核心特性

2.1 类型安全的路由

import { elegantRouter, route } from 'elegant-router'

// 定义路由
export const routes = elegantRouter({
  // 基础路由
  home: route('/', () => import('@/views/Home.vue')),

  // 带参数的路由
  user: route('/user/:id', () => import('@/views/User.vue'), {
    props: true // 自动传递参数
  }),

  // 嵌套路由
  dashboard: route('/dashboard', () => import('@/views/Dashboard.vue'), {
    children: {
      overview: route('overview', () => import('@/views/Dashboard/Overview.vue')),
      settings: route('settings', () => import('@/views/Dashboard/Settings.vue'))
    }
  })
})

// 使用时的类型安全
const router = useRouter()

// ✅ 自动补全路由名
router.push({ name: 'user', params: { id: 1 } })

// ❌ 类型错误:缺少 params
router.push({ name: 'user' }) 

// ❌ 类型错误:不存在的路由
router.push({ name: 'not-exist' })

2.2 自动生成路由类型

// elegant-router 自动生成的路由类型
type AppRoutes = {
  home: { path: '/'; params?: never; query?: any }
  user: { path: '/user/:id'; params: { id: string }; query?: any }
  dashboard: { 
    path: '/dashboard'; 
    params?: never; 
    query?: any;
    children: {
      overview: { path: 'overview'; params?: never; query?: any }
      settings: { path: 'settings'; params?: never; query?: any }
    }
  }
}

// 使用时获得完整的类型提示
const { name, params, query } = routeTo('user', { id: '123' })
// name: 'user'
// params: { id: string }

3. 基本使用

3.1 安装和配置

# 安装
npm install elegant-router
# 或
yarn add elegant-router
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import { elegantRouter, route, setupElegantRouter } from 'elegant-router'
import type { App } from 'vue'

// 1. 定义路由
export const routes = elegantRouter({
  // 首页
  home: route('/', () => import('@/views/Home.vue')),

  // 关于页
  about: route('/about', () => import('@/views/About.vue')),

  // 用户相关
  user: {
    // 用户列表
    list: route('/users', () => import('@/views/user/List.vue')),

    // 用户详情
    detail: route('/users/:id', () => import('@/views/user/Detail.vue'), {
      props: true
    }),

    // 用户编辑
    edit: route('/users/:id/edit', () => import('@/views/user/Edit.vue'))
  },

  // 管理后台
  admin: route('/admin', () => import('@/views/Admin.vue'), {
    meta: { requiresAuth: true, role: 'admin' },
    children: {
      dashboard: route('', () => import('@/views/admin/Dashboard.vue')),
      users: route('users', () => import('@/views/admin/Users.vue'))
    }
  }),

  // 404 页面
  notFound: route('/:pathMatch(.*)*', () => import('@/views/404.vue'))
})

// 2. 创建 Vue Router
export const router = createRouter({
  history: createWebHistory(),
  routes: routes.flat // 转换为 Vue Router 格式
})

// 3. 安装插件
export function setupRouter(app: App) {
  app.use(router)
  setupElegantRouter(router, routes)

  return router
}

3.2 在 main.ts 中使用

// main.ts
import { createApp } from 'vue'
import { setupRouter } from './router'
import App from './App.vue'

async function bootstrap() {
  const app = createApp(App)

  // 安装路由
  await setupRouter(app)

  app.mount('#app')
}

bootstrap()

4. 路由跳转

4.1 类型安全的导航

<template>
  <div>
    <!-- 1. 编程式导航 -->
    <button @click="goToUser">用户详情</button>

    <!-- 2. 路由链接 -->
    <router-link :to="routeTo('user.detail', { id: '123' })">
      用户123
    </router-link>
  </div>
</template>

<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'
import { routeTo, useRouteParams } from 'elegant-router'

const router = useRouter()
const route = useRoute()

// ✅ 类型安全的跳转
const goToUser = () => {
  // 方法1: 使用 routeTo 辅助函数
  router.push(routeTo('user.detail', { id: '123' }))

  // 方法2: 直接使用 router.push
  router.push({ 
    name: 'user.detail', 
    params: { id: '123' } 
  })

  // ❌ 类型错误:缺少必要参数
  // router.push({ name: 'user.detail' })

  // ❌ 类型错误:参数类型不匹配
  // router.push({ name: 'user.detail', params: { id: 123 } })
}

// 获取路由参数(类型安全)
const params = useRouteParams('user.detail')
// params 类型为 { id: string }
console.log(params.id) // 自动提示 id 属性
</script>

4.2 查询参数和哈希

// 带查询参数的路由
router.push(
  routeTo('user.list', null, { 
    page: 1, 
    size: 20,
    search: 'keyword'
  })
)

// 带哈希的路由
router.push(
  routeTo('about', null, null, '#section-2')
)

// 完整参数
const to = routeTo(
  'user.detail',      // 路由名
  { id: '123' },      // 路径参数
  { tab: 'info' },    // 查询参数
  '#profile'          // 哈希
)

5. 高级功能

5.1 路由守卫

// router/guards.ts
import type { RouteLocationNormalized } from 'vue-router'
import { useAuthStore } from '@/stores/auth'

// 类型安全的守卫
export function authGuard(
  to: RouteLocationNormalized,
  from: RouteLocationNormalized
) {
  const authStore = useAuthStore()

  // 检查是否需要认证
  if (to.meta.requiresAuth && !authStore.isAuthenticated) {
    // 重定向到登录页
    return routeTo('login', null, { 
      redirect: to.fullPath 
    })
  }

  // 检查角色权限
  if (to.meta.role && !authStore.hasRole(to.meta.role)) {
    return routeTo('forbidden')
  }
}

5.2 动态路由

// 动态添加路由
import { addRoute } from 'elegant-router'

// 基于权限动态添加路由
function setupDynamicRoutes(userRole: string) {
  if (userRole === 'admin') {
    addRoute('admin', {
      system: route('system', () => import('@/views/admin/System.vue'), {
        meta: { requiresAdmin: true }
      })
    })
  }
}

5.3 路由元信息

export const routes = elegantRouter({
  dashboard: route('/dashboard', () => import('@/views/Dashboard.vue'), {
    // 路由元信息
    meta: {
      title: '控制台',
      requiresAuth: true,
      breadcrumb: ['首页', '控制台'],
      icon: 'dashboard',
      keepAlive: true,
      permissions: ['view_dashboard']
    },

    // 路由独享的守卫
    beforeEnter: (to, from) => {
      // 类型安全的守卫
      console.log(to.params) // 有完整类型提示
    }
  })
})

6. 工具函数

6.1 路由辅助工具

import { 
  routeTo,          // 生成路由对象
  useRouteParams,   // 获取类型安全的参数
  useRouteQuery,    // 获取类型安全的查询参数
  useRouteHash,     // 获取哈希
  getRouteMeta,     // 获取路由元信息
  resolveRoute,     // 解析路由
  generatePath      // 生成路径
} from 'elegant-router'

// 在组件中使用
const UserDetail = defineComponent({
  setup() {
    // 获取参数(类型安全)
    const params = useRouteParams('user.detail')
    const query = useRouteQuery('user.list')
    const hash = useRouteHash()

    // 获取元信息
    const meta = getRouteMeta('dashboard')

    // 生成路径
    const path = generatePath('user.detail', { id: '123' })
    // 输出: /users/123

    return { params, path }
  }
})

7. 实际项目结构

7.1 推荐的项目结构

src/
├── router/
│   ├── index.ts              # 主路由文件
│   ├── types/               # 路由类型定义
│   │   ├── index.ts
│   │   └── meta.ts         # 元信息类型
│   ├── guards/             # 路由守卫
│   │   ├── auth.ts
│   │   └── permission.ts
│   └── modules/            # 路由模块
│       ├── auth.routes.ts
│       ├── user.routes.ts
│       └── admin.routes.ts
├── views/                  # 页面组件
│   ├── Home.vue
│   ├── user/
│   │   ├── List.vue
│   │   └── Detail.vue
│   └── admin/
│       ├── Dashboard.vue
│       └── Users.vue
└── App.vue

7.2 模块化路由示例

// router/modules/auth.routes.ts
export const authRoutes = {
  login: route('/login', () => import('@/views/auth/Login.vue')),
  register: route('/register', () => import('@/views/auth/Register.vue')),
  forgotPassword: route('/forgot-password', () => import('@/views/auth/ForgotPassword.vue'))
}

// router/modules/user.routes.ts  
export const userRoutes = {
  profile: route('/profile', () => import('@/views/user/Profile.vue'), {
    meta: { requiresAuth: true }
  }),
  settings: route('/settings', () => import('@/views/user/Settings.vue'), {
    meta: { requiresAuth: true }
  })
}

// router/index.ts
import { authRoutes, userRoutes } from './modules'

export const routes = elegantRouter({
  ...authRoutes,
  ...userRoutes,
  // 其他路由...
})

8. 与 Vue Router 对比

特性 Vue Router elegant-router
类型安全 ❌ 有限 ✅ 完整
自动补全 ❌ 无 ✅ 完整
路由定义 对象数组 类型安全对象
参数验证 ❌ 运行时 ✅ 编译时
元信息 松散类型 严格类型
学习成本
适用场景 所有项目 中大型 TypeScript 项目

9. 总结

elegant-router 的核心价值

✅ 优点:

  1. 完整的类型安全 - 编译时检查路由
  2. 优秀的开发体验 - 自动补全、类型提示
  3. 更好的代码组织 - 模块化、可维护
  4. 减少运行时错误 - 提前发现路由问题

⚠️ 注意事项:

  1. 需要 TypeScript 项目
  2. 学习成本略高
  3. 更适合中大型项目

🎯 适用场景:

  • 使用 Vue 3 + TypeScript 的项目
  • 中大型企业级应用
  • 需要严格路由管理的项目
  • 团队协作,需要规范路由使用

如果你在开发一个 TypeScript 的 Vue 3 项目,并且对代码质量有要求,elegant-router 是一个很不错的选择.