深入 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.pushStatehistory.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: 工程化工具层

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

相关推荐
一颗小青松4 小时前
css 文字区域根据图片形状显示,根据文字设置背景图
前端·css
阿黎梨梨4 小时前
跟 Git 打交道的正确姿势
前端
idcu4 小时前
用 Lyt.js 构建 Todo 应用:完整教程
前端·typescript
七夜zippoe4 小时前
DolphinDB时间序列引擎:实时聚合计算
服务器·前端·时间序列·dolphindb·实时聚合
佳木逢钺4 小时前
pnpm 命令功能清单
前端
m0_738120724 小时前
渗透测试基础知识——从零认识JWT(JSON Web Token)身份令牌
服务器·前端·安全·web安全·网络安全·json
放下华子我只抽RuiKe54 小时前
React 从入门到生产(六):路由与导航
前端·人工智能·深度学习·react.js·前端框架·html·claude code
Sylus_sui4 小时前
实现:每行固定 5 个、自动换行、最后一行左对齐、数量不固定
前端·javascript·css
文滨4 小时前
10分钟搞定!Mac 配置 GitHub SSH 完全指南(小白也能看懂)
前端·macos·ssh·github