深入 Lyt.js 路由系统:L6 生态系统层的核心

深入 Lyt.js 路由系统:L6 生态系统层的核心

基于 Lyt.js v6.6.0 @lytjs/router 和 @lytjs/router-fs 包源码,深入解析路由系统的设计理念、导航守卫、路由匹配和文件系统路由。

一、路由系统架构

在 Lyt.js v6.6.0 的 8 层架构中,路由系统位于 L6 生态系统层:

makefile 复制代码
L5: 组件基础层
L4: 插件与适配层
L3: 核心运行时层
L2: 渲染引擎层
L1: 核心原语层
  ↓
L6: 生态系统层
  ├── @lytjs/router (路由系统)
  ├── @lytjs/router-fs (文件系统路由)
  ├── @lytjs/api (API 路由)
  ├── @lytjs/store (状态管理)
  ├── @lytjs/ui (UI 组件库)
  └── ...

二、快速开始

typescript 复制代码
import { createApp } from '@lytjs/core'
import { createRouter, createWebHistory } from '@lytjs/router'
import Home from './views/Home.lyt'
import About from './views/About.lyt'
import User from './views/User.lyt'

const router = createRouter({
  mode: 'history',
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/user/:id', component: User },
  ]
})

const app = createApp(App)
app.use(router)
app.mount('#app')

三、路由模式

Lyt.js 支持两种路由模式:

3.1 History 模式

使用 HTML5 History API,适合有服务器配置的场景:

typescript 复制代码
import { createWebHistory } from '@lytjs/router'

const router = createRouter({
  mode: 'history',
  history: createWebHistory('/app'),
  routes: [...]
})

特点:

  • URL 更加美观(/user/123)
  • 需要服务器配置处理 404
  • 支持 history.pushState 和 history.replaceState
3.2 Hash 模式

使用 URL hash(#),无需服务器配置:

typescript 复制代码
import { createHashHistory } from '@lytjs/router'

const router = createRouter({
  mode: 'hash',
  routes: [...]
})

特点:

  • 无需服务器配置
  • URL 包含 #(/#/user/123)
  • 适合静态托管环境

四、路由定义

4.1 基础路由
typescript 复制代码
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/contact', component: Contact },
]
4.2 动态路由
typescript 复制代码
const routes = [
  { path: '/user/:id', component: User },
  { path: '/post/:category/:slug', component: Post },
  { path: '/order/:id?', component: Order }, // 可选参数
]
4.3 嵌套路由
typescript 复制代码
const routes = [
  {
    path: '/user/:id',
    component: UserLayout,
    children: [
      { path: '', component: UserProfile },
      { path: 'posts', component: UserPosts },
      { path: 'settings', component: UserSettings },
    ]
  }
]
4.4 命名路由
typescript 复制代码
const routes = [
  {
    path: '/user/:id',
    name: 'user',
    component: User
  }
]

// 编程式导航
router.push({ name: 'user', params: { id: '123' } })
4.5 别名路由
typescript 复制代码
const routes = [
  { path: '/home', component: Home, alias: '/' }
]

五、路由参数

5.1 组件中获取参数
typescript 复制代码
// 方式一:通过 inject
import { useRoute } from '@lytjs/router'

const route = useRoute()
console.log(route.params.id)    // URL 参数
console.log(route.query.search) // 查询参数
console.log(route.hash)         // hash 值

// 方式二:通过 $route
defineComponent({
  template: '<p>User ID: {{ $route.params.id }}</p>'
})
5.2 参数变化监听
typescript 复制代码
const route = useRoute()

// 监听参数变化
watch(
  () => route.params.id,
  (newId, oldId) => {
    console.log(`ID 从 ${oldId} 变为 ${newId}`)
    // 重新获取数据
  }
)

六、导航守卫

6.1 全局前置守卫
typescript 复制代码
router.beforeEach((to, from, next) => {
  // to: 目标路由
  // from: 当前路由
  // next: 继续导航的函数
  
  if (to.meta.requiresAuth && !isLoggedIn()) {
    next('/login')
  } else {
    next()
  }
})
6.2 全局解析守卫
typescript 复制代码
router.beforeResolve((to, from, next) => {
  // 在导航被确认前,所有组件内守卫和异步路由组件被解析之后调用
  // 适合做数据预获取
  fetchData(to.params.id).then(data => {
    to.meta.data = data
    next()
  })
})
6.3 全局后置钩子
typescript 复制代码
router.afterEach((to, from) => {
  // 导航确认后调用
  document.title = to.meta.title || 'Lyt.js App'
  analytics.pageView(to.path)
})
6.4 路由独享守卫
typescript 复制代码
const routes = [
  {
    path: '/admin',
    component: Admin,
    beforeEnter: (to, from, next) => {
      if (isAdmin()) {
        next()
      } else {
        next('/403')
      }
    }
  }
]
6.5 组件内守卫
typescript 复制代码
defineComponent({
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被确认前调用
    // 不能访问 this
    next(vm => {
      // 通过 vm 访问组件实例
    })
  },
  
  beforeRouteUpdate(to, from, next) {
    // 在当前路由改变,但该组件被复用时调用
    // 适合处理参数变化
  },
  
  beforeRouteLeave(to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问 this
    if (hasUnsavedChanges()) {
      const answer = confirm('有未保存的更改,确定离开吗?')
      if (answer) {
        next()
      } else {
        next(false)
      }
    } else {
      next()
    }
  }
})
6.7 导航守卫执行顺序
  1. 导航触发
  2. 失活的组件调用 beforeRouteLeave
  3. 全局 beforeEach
  4. 复用组件调用 beforeRouteUpdate
  5. 路由独享 beforeEnter
  6. 解析异步路由组件
  7. 激活组件调用 beforeRouteEnter
  8. 全局 beforeResolve
  9. 导航确认
  10. 全局 afterEach

七、编程式导航

7.1 基础导航
typescript 复制代码
// 字符串路径
router.push('/user/123')

// 对象路径
router.push({ path: '/user/123' })

// 命名路由
router.push({ name: 'user', params: { id: '123' } })

// 带查询参数
router.push({ path: '/search', query: { q: 'vue' } })

// 替换当前记录
router.replace('/home')

// 前进/后退
router.go(1)   // 前进
router.go(-1)  // 后退
router.back()  // 后退
router.forward() // 前进
7.2 导航控制
typescript 复制代码
// 取消导航
router.beforeEach((to, from, next) => {
  if (needsGuard(to)) {
    next(false) // 取消导航
  } else {
    next()
  }
})

// 重定向
router.beforeEach((to, from, next) => {
  if (to.path === '/old') {
    next('/new')
  } else {
    next()
  }
})

// 导航错误
router.onError(error => {
  console.error('导航错误:', error)
})

八、元信息(Meta)

8.1 定义 Meta
typescript 复制代码
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true,
      role: 'admin',
      title: '管理后台'
    }
  }
]
8.2 访问 Meta
typescript 复制代码
router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    // 需要认证
  }
  if (to.meta.role === 'admin') {
    // 需要管理员权限
  }
  next()
})

九、路由懒加载

9.1 箭头函数
typescript 复制代码
const routes = [
  { path: '/home', component: () => import('./views/Home.vue') },
  { 
    path: '/about', 
    component: () => import('./views/About.vue')
      .then(m => m.default) // 支持 Promise
  }
]
9.2 路由懒加载 + Loading
typescript 复制代码
import { defineAsyncComponent } from '@lytjs/core'

const routes = [
  {
    path: '/dashboard',
    component: defineAsyncComponent({
      loader: () => import('./views/Dashboard.vue'),
      loadingComponent: LoadingSpinner,
      errorComponent: ErrorBoundary,
      delay: 200,
      timeout: 3000
    })
  }
]
9.3 路由分组
typescript 复制代码
// 将某个路由下的所有组件都打包在同一个异步块中
const routes = [
  {
    path: '/admin',
    component: AdminLayout,
    children: [
      { path: 'users', component: () => import('./views/AdminUsers.vue') },
      { path: 'settings', component: () => import('./views/AdminSettings.vue') }
    ]
  }
]

十、过渡动画

typescript 复制代码
// 路由过渡
defineComponent({
  template: `
    <Transition name="fade" mode="out-in">
      <router-view />
    </Transition>
  `
})

// CSS
.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.3s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

十一、路由类型安全

Lyt.js 支持 TypeScript 类型推导:

typescript 复制代码
import type { RouteRecordRaw } from '@lytjs/router'

const routes: RouteRecordRaw[] = [
  {
    path: '/user/:id',
    name: 'User',
    component: () => import('./views/User.vue'),
    props: true, // 将路由参数作为 props 传递给组件
    children: [
      {
        path: 'posts',
        component: () => import('./views/UserPosts.vue')
      }
    ]
  }
]

// 组件中使用
defineComponent({
  props: {
    id: String // 从路由参数自动获取
  },
  setup(props) {
    // props.id 已有类型
  }
})

十二、文件系统路由

Lyt.js v6.6.0 提供了 @lytjs/router-fs 包,支持基于文件系统的路由:

bash 复制代码
src/
└── pages/
    ├── index.lyt          → /
    ├── about.lyt          → /about
    ├── user/
    │   ├── index.lyt     → /user
    │   └── [id].lyt      → /user/:id
    └── blog/
        ├── index.lyt      → /blog
        └── [slug].lyt    → /blog/:slug
typescript 复制代码
import { createFileSystemRouter } from '@lytjs/router-fs'

const router = createFileSystemRouter('./src/pages', {
  extensions: ['.lyt', '.vue'],
  // 导入模式
  importMode: 'async', // 'sync' | 'async' | (path) => Promise
  // 路由选项
  routes: {
    index: { name: 'home' },
    dynamic: { prefix: '[' }
  }
})

十三、在 v6.6.0 中的位置

路由系统在 8 层架构中的位置:

bash 复制代码
L1: 核心原语层
  ├── @lytjs/reactivity
  ├── @lytjs/vdom
  └── @lytjs/compiler
L2: 渲染引擎层
  ├── @lytjs/renderer
  ├── @lytjs/component
  └── @lytjs/dom-runtime
L3: 核心运行时层
  └── @lytjs/core
L4: 插件与适配层
  ├── @lytjs/plugin-auth (权限插件)
  └── ...
L5: 组件基础层
L6: 生态系统层 ← 当前层
  ├── @lytjs/router
  ├── @lytjs/router-fs
  ├── @lytjs/store
  └── ...
L7: 工程化工具层

路由系统依赖核心运行时层,同时被插件层(如权限插件)扩展。

相关推荐
螺丝钉tina8 分钟前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
小天源1 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库
Highcharts.js2 小时前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
薛定谔的猫-菜鸟程序员3 小时前
Electron开发超详细教程(从入门到放弃)
前端·javascript·electron
最强小杰3 小时前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
静水leo4 小时前
使用 Whistle 拦截接口并模拟后端响应
前端
掘金者阿豪4 小时前
SQL Server数据迁移完成后,凌晨的数据库告警该怎么查?
前端·后端
JudithHuang4 小时前
React 嵌套路由与布局
前端·react.js·arcgis·react·react router
htzyl2064 小时前
前端阶梯——第四十三章、实战二:待办清单To-Do
前端·javascript·html