使用 UniApp、Vue、TypeScript 和 Vite 构建高效的路由管理系统
在现代前端开发中,路由管理是构建单页应用(SPA)时不可或缺的一部分。本文将介绍如何使用 UniApp、Vue、TypeScript 和 Vite 技术栈来实现一个灵活且高效的路由管理系统。我们将逐步解析实现代码的各个部分,帮助读者深入理解其功能和实现原理。
技术栈概述
- UniApp:一个使用 Vue.js 开发跨平台应用的框架。
- Vue:流行的 JavaScript 框架,用于构建用户界面。
- TypeScript:JavaScript 的超集,提供静态类型检查。
- Vite:下一代前端工具,提供快速的构建和热重载。
路由管理代码解析
1. 引入依赖和类型定义
import type { PageMetaDatum, PagesConfig } from '@uni-helper/vite-plugin-uni-pages'
import type { NavigateToOptions, SwitchTabOptions } from '@/uni-pages'
import type { MiddlewareFn } from '@/defineMiddleware'
import pagesJson from '@/pages.json'
const { pages, tabBar } = pagesJson as any as Required<PagesConfig>
首先,我们引入了必要的类型定义和页面配置。通过 import type 引入了类型,确保代码的类型安全,并从 pages.json 文件中读取页面和 TabBar 配置。
2. 类型定义
export type RouterOption = UniNamespace.NavigateToOptions & (NavigateToOptions | SwitchTabOptions)
export type RoutePath = NavigateToOptions['url']
在此部分,我们定义了路由选项的类型 RouterOption,结合了 UniApp 的导航选项和自定义的选项。同时,提取了导航选项中的 URL 类型作为 RoutePath。
3. 页面字典和 TabBar 路径
const pageDic = pages.reduce((a: any, b: any) => ((a[b.path.startsWith('/') ? b.path : `/${b.path}`] = b), a), {} as Record<string, any>)
const tabBarPaths = tabBar?.list?.map(b => b!.path.startsWith('/') ? b!.path : `/${b!.path}`) || []
const pagePaths = Object.keys(pageDic)
我们通过 reduce 方法将页面信息转换为字典,方便后续查找。同时,提取 TabBar 的路径并确保路径以 / 开头。
4. 获取文件名的函数
function getFileName(path: string): string {
const p = path.split('/')
return p[p.length - 1].split('.')[0]
}
此函数用于从给定的路径中提取文件名,去掉扩展名,为后续处理中间件时使用。
5. 中间件文件处理
const middlewareFile = import.meta.glob('../middleware/*.ts', { eager: true })
const middlewareFileDic = Object.entries(middlewareFile).reduce<Record<string, MiddlewareFn>>((a: any, b: any) => ((a[getFileName(b[0])] = b[1].default), a), {} as Record<string, MiddlewareFn>)
使用 Vite 的 import.meta.glob 动态导入所有中间件文件,并将中间件文件转换为字典,方便根据名字快速查找和调用。
6. 获取路由选项的函数
function getOption(option: RouterOption | RoutePath): RouterOption {
if (typeof option === 'object') return option
return { url: option }
}
该函数统一处理路由选项,如果传入的是对象则直接返回,否则将路径封装成对象返回。
7. 中间件处理逻辑
function handleMiddleware(option: RouterOption, currentPage: any) {
const midFnNames = pageDic[option.url as string]?.middleware
if (midFnNames && Array.isArray(midFnNames)) {
for (let index = 0; index < midFnNames.length; index++) {
const taskName = midFnNames[index]
if (!(taskName in middlewareFileDic)) throw new Error(`不存在的middleware 在 ${option.url}`)
const path = middlewareFileDic[taskName](option, currentPage)
if (path != null) {
to(getOption(path))
return false
}
}
}
return true
}
此函数处理当前路由的中间件逻辑,通过页面字典查找当前路由的中间件函数名并依次执行中间件函数。
8. 路由跳转逻辑
function to(option: RouterOption, fn?: Uni['redirectTo'] | Uni['reLaunch']) {
const res = middlewareDistribute(option)
if (res === true) {
if (pagePaths.some(v => option.url.startsWith(v)))
return fn ? fn(option) : uni.navigateTo(option)
else if (tabBarPaths.some(v => option.url.startsWith(v)))
return uni.switchTab(option)
else
throw new Error(`不存在的页面`)
}
return false
}
该函数负责执行路由跳转,首先调用 middlewareDistribute 处理中间件,然后根据路径判断是普通页面跳转还是 TabBar 切换,调用相应的 UniApp 方法。
9. Router 类的实现
export class router {
static push(option: RouterOption | RoutePath) {
const _op = getOption(option)
return to(_op)
}
static back(option: UniNamespace.NavigateBackOptions | number = 1) {
const pages = getCurrentPages()
if (pages.length === 1) {
router.redirect('/pages/index/index')
} else {
const op = typeof option === 'object' ? option : { delta: option }
return uni.navigateBack(op)
}
}
static redirect(option: RouterOption | RoutePath) {
const _op = getOption(option)
return to(_op, uni.redirectTo)
}
static reLaunch(option: RouterOption | RoutePath) {
const _op = getOption(option)
return to(_op, uni.reLaunch)
}
static current<P extends boolean>(quote?: P): (P extends true ? Page.PageInstance : PageMetaDatum) | null {
const pages = getCurrentPages()
const page = pages[pages.length - 1]
if (!page) return null
const route = page.route?.startsWith('/') ? page.route : `/${page.route}`
if (quote) {
page.route = route
return page as any
}
return pageDic[route] as any
}
}
router 类提供了一系列静态方法供外部调用,包括:
- push:用于跳转到新页面。
- back:返回上一个页面,支持指定返回的层级。
- redirect:重定向到指定页面。
- reLaunch:重新启动应用,跳转到指定页面。
- current:获取当前页面的信息,支持返回完整的页面实例或元数据。
总结
通过以上的代码解析,我们深入理解了如何利用 UniApp、Vue、TypeScript 和 Vite 构建一个高效的路由管理系统。这个系统不仅支持基本的路由跳转功能,还能够灵活地处理中间件,增强了应用的可维护性和扩展性。希望这篇文章能为你的项目提供一些启发和帮助!