Slidev 客户端路由扩展:用 setup/routes.ts 为演示应用添加自定义页面

发布时间:2026/9/6 20:16:22
Slidev 客户端路由扩展:用 setup/routes.ts 为演示应用添加自定义页面 Slidev 客户端路由扩展用 setup/routes.ts 为演示应用添加自定义页面【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev本文讲解 Slidev 的路由自定义机制通过在项目根目录创建./setup/routes.ts并导出defineRoutesSetup配置你可以在 Slidev 应用内置的路由表之上追加任意自定义页面如独立的资料页、测验页、致谢页等。读完本文后你将掌握路由 setup 的完整写法、它与内置路由play、presenter、print、export、404的合并方式以及该机制背后基于 Vite 虚拟模块的加载原理。为什么需要自定义路由Slidev 本身是一个基于 Vue Router 的 SPA幻灯片页面、演讲者模式、打印、导出等入口都注册为独立路由。从源码 packages/client/setup/routes.ts 可以看到内置路由的完整清单路由所属功能开关说明/:noplay始终启用播放幻灯片路径为空时重定向到/1/:pathMatch(.*)*NotFound始终启用兜底 404 页面/entry、/overview、/notes、/notes-edit、/presenter/:no__SLIDEV_FEATURE_PRESENTER__演讲者模式相关页面/print、/presenter/print__SLIDEV_FEATURE_PRINT__打印/导出 PDF 页面/export/:no?__SLIDEV_FEATURE_BROWSER_EXPORTER__浏览器端导出页面当你的演示需要幻灯片之外的页面例如一个独立的「附录」页、在线表单页、测验页时官方提供的扩展点就是setup/routes.ts。该文档属于客户端client环境配置对应官方文档为 docs/custom/config-routes.md。使用方式在项目根目录创建./setup/routes.ts内容如下与官方文档一致import { defineRoutesSetup } from slidev/types export default defineRoutesSetup((routes) { return [ ...routes, { path: /my-page, // ---cut-start--- // ts-expect-error missing types // ---cut-end--- component: () import(../pages/my-page.vue), }, ] })要点说明回调参数routes是 Slidev 内置的全部路由记录RouteRecordRaw[]...routes展开后保留所有内置页面新增路由使用 Vue Router 的标准格式path 懒加载的component这里按文档示例引用../pages/my-page.vue即你在项目根目录下自行创建的./pages/my-page.vue组件文件文档中的// ts-expect-error missing types注释是官方代码块twoslash 校验的一部分表示该位置存在类型缺失实际项目中是否保留可自行判断路由的其他字段name、meta、beforeEnter、redirect等遵循 Vue Router 规范官方文档建议参考 Vue Router 的文档进一步学习。如果你还想在自定义页面里访问幻灯片状态当前页码、幻灯片信息等可以直接使用 Slidev 客户端提供的 composable例如useSlideInfo这些状态与路由相互独立在自定义页面中同样可用。路由如何被合并内置路由与用户 setup 的执行顺序理解「自定义页面为什么会生效」需要看内置路由的返回逻辑。packages/client/setup/routes.ts 的最后一行return setups.reduce((routes, setup) setup(routes), routes)它把内置路由数组依次交给每一个用户routes setup处理——你导出的defineRoutesSetup回调正是其中一环。这意味着先组装内置路由再交给用户代码你的回调拿到的routes已经包含 play、404 兜底路由以及按功能开关条件加入的 presenter/print/export 路由你可以增、也可以改由于回调拿到的是完整数组你不仅可以追加路由还可以过滤routes.filter(...)、修改或替换其中任意一条记录后再返回404 兜底路由也在此数组中它被声明为/:pathMatch(.*)*Vue Router 按路径特异性评分匹配静态路径/my-page的得分高于通配兜底因此自定义页面不会被 404 抢走若你希望自定义页面接管某些未匹配路径也可以在回调中重新排序或调整兜底路由。另外值得注意的是presenter、print、export 等路由在注册时都挂了beforeEnter: passwordGuard见 packages/client/setup/routes.ts#L8-L20当配置了远程密码remote时这些敏感页面会校验?password查询参数。你在自定义页面中如果涉及敏感内容也可以参照这一模式为自定义路由添加beforeEnter守卫。底层机制虚拟模块如何找到你的 setup/routes.ts客户端代码里对#slidev/setups/routes的导入由 Slidev 的 Vite 插件在构建期动态生成为虚拟模块/slidev/setups/routes。生成逻辑位于 packages/slidev/node/virtual/setups.tsfunction createSetupTemplate(name: string): VirtualModuleTemplate { const id /slidev/setups/${name} return { id, getContent({ roots }) { // 对每个 root 目录做 globsetup/${name}.{ts,js,mts,mjs} // 用 makeAbsoluteImportGlob 生成 import 语句 // 最终输出 export default [各root的setup默认导出].filter(Boolean) }, } } const setupModules [shiki, code-runners, monaco, mermaid, mermaid-renderer, main, root, routes, shortcuts, context-menu]从中可以确认几个实操层面的事实文件名与扩展名约定目录是setup/注意无 s文件名是routes扩展名支持.ts / .js / .mts / .mjs四种不限于 TypeScript多入口支持生成代码会对每个根目录roots做 glob即多入口 slides 项目可以为不同根目录各自提供setup/routes.ts未匹配到时以filter(Boolean)过滤不会报错默认导出约定每个 setup 模块取的是default导出这就是文档示例中export default defineRoutesSetup(...)的原因类型声明虚拟模块的类型由 packages/types/client.d.ts 声明为RoutesSetup[]其中RoutesSetup的定义在 packages/types/src/setups.ts#L100export type RoutesSetup (routes: RouteRecordRaw[]) RouteRecordRaw[]defineRoutesSetup则是标准的defineSetup包装packages/types/src/setups.ts#L117仅用于固定回调签名、提供 IDE 补全本身不做任何运行时处理。#slidev/*与/slidev/*的别名关系也在该文件头部注释中说明由于 TS 会把/slidev/*当作绝对路径而无法覆盖因此客户端代码统一以#slidev/前缀导入虚拟模块。路由在应用启动中的位置自定义路由最终在应用初始化时参与创建 Router。入口流程见 packages/client/setup/main.ts#L24-L31const router createRouter({ history: __SLIDEV_MEMORY_ROUTE__ ? createMemoryHistory(import.meta.env.BASE_URL) : __SLIDEV_HASH_ROUTE__ ? createWebHashHistory(import.meta.env.BASE_URL) : createWebHistory(import.meta.env.BASE_URL), routes: setupRoutes(), // ← 内置路由 用户 setup 合并后的结果 })这带来两点实用信息history 模式影响 URL普通开发/预览使用 HTML5 historyURL 为/my-page若通过 hash 路由模式访问则为#/my-page导出 PDF 等场景使用 memory history自定义页面同样按路径寻址路由 setup 早于 main setup 执行setupRoutes()在createRouter时即完成而#slidev/setups/main中的各AppSetup负责挂载自定义指令、PWA 等在其后顺序执行因此你的自定义页面在挂载前就已经可被路由到。顺带一提Node 侧存在一个对称的加载器 packages/slidev/node/setups/load.ts它按同样的setup/filename约定在服务端如解析 slides、生成虚拟模块内容时加载 setup 文件客户端的routes虚拟模块正是把同一批文件打包进浏览器端执行。两者共享setup/目录约定这解释了为什么文件名、扩展名必须严格遵循约定。完整示例为演示添加一个附录页结合上述机制一个可直接运行的最小实践如下。创建自定义页面组件./pages/my-page.vuescript setup langts // 自定义页面中可以像普通 Vue 组件一样使用组合式 API // 也可以按需引入 slidev/client 提供的状态与 composable /script template div classtext-6xl p-10 h1我的自定义页面/h1 p这个页面由 setup/routes.ts 注册与幻灯片路由共存。/p /div /template创建./setup/routes.ts注册路由即「使用方式」一节的代码确保path不与内置路由冲突如避免使用/1、/print等已被占用的路径启动开发服务后访问/my-page页面即由你注册的组件渲染若配置了basePath部署在子路径下URL 前缀会由 Vue Router 的history基地址import.meta.env.BASE_URL见 packages/client/setup/main.ts#L24-L29自动处理。注意事项与适用前提环境前提该配置属于客户端clientsetup依赖 Slidev 的 Vite 插件注入的虚拟模块与__SLIDEV_FEATURE_*__编译期常量只能在slidev/slidev驱动的 Vite 应用中生效不能脱离 Slidev 工程直接使用回调必须返回路由数组RoutesSetup签名为(routes) routes返回undefined会导致后续app.use(router)注册失败不要意外移除内置路由如果你只想追加页面请始终...routes保留原数组文档示例的做法否则 404 兜底或播放路由可能丢失类型提示可能不完整文档示例中特意用ts-expect-error标记了类型缺口若你在 IDE 中看到红色波浪线优先检查slidev/types版本与项目 TS 配置是否一致进阶场景若需要在路由跳转前后做埋点、埋自定义导航逻辑可以改用beforeEnter守卫或直接在自定义页面中使用useRouter这些都遵循 Vue Router 的标准用法。小结Slidev 的自定义路由机制本质上是一条清晰的管线内置路由在 packages/client/setup/routes.ts 中按功能开关组装经由虚拟模块#slidev/setups/routes由 packages/slidev/node/virtual/setups.ts 从各根目录的setup/routes.{ts,js,mts,mjs}动态生成收集用户的defineRoutesSetup回调最后通过reduce链合并并交给createRouter。你只要创建./setup/routes.ts、保留内置路由、追加自己的path component就能在幻灯片应用中获得任意自定义页面且整个过程的类型与运行行为都有 packages/types/src/setups.ts 和 packages/types/client.d.ts 中的声明作为依据。【免费下载链接】slidevPresentation Slides for Developers项目地址: https://gitcode.com/GitHub_Trending/sl/slidev创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考