更新记录
1.0.0(2025-11-14) 下载此版本
平台兼容性
uni-app(4.19)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
|---|---|---|---|---|---|---|---|---|
| × | √ | √ | √ | √ | - | - | - | - |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | - | - | - | - | - | - | - | - | - |
uni-router-enhance
一个为 uni-app 设计的类型安全路由增强库,提供完整的 TypeScript 类型支持、路由守卫、动态处理函数等高级特性。
✨ 特性
- 🔒 完全类型安全 - 基于
pages.json自动生成路由类型,避免路由拼写错误 - 🛡️ 导航守卫 - 支持
beforeEach和afterEach全局守卫 - 🎯 动态处理函数 - 为特定路由注册数据预加载、权限检查等处理逻辑
- 📦 查询参数类型化 - 支持 TypeScript 类型推断的查询参数
- 🔄 自动类型生成 - Vite 插件自动从
pages.json生成路由类型 - 🎨 灵活的页面关闭策略 - 支持
navigateTo、redirectTo、reLaunch等多种跳转方式 - 💾 路由数据缓存 - 自动缓存查询参数和处理函数返回值
📦 安装
npm install uni-router-enhance
# 或
pnpm add uni-router-enhance
# 或
yarn add uni-router-enhance
🚀 快速开始
1. 配置 Vite 插件
在 vite.config.ts 中配置自动类型生成插件:
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
import { routeTypesPlugin } from 'uni-router-enhance'
export default defineConfig({
plugins: [
uni(),
// 自动从 pages.json 生成路由类型
routeTypesPlugin('./types/auto-page.d.ts')
]
})
2. 创建 Router 实例
在 src/router/index.ts 中创建 router 实例:
import { createRouter } from 'uni-router-enhance'
import pagesJson from '../pages.json'
import type { ENHANCE_ROUTE_PATH } from '../../types/auto-page.d.ts'
// 创建路由实例,传入 pages.json 配置
const router = createRouter<ENHANCE_ROUTE_PATH>(pagesJson)
// 配置全局前置守卫
router.beforeEach((to, from) => {
console.log('导航前:', to, from)
// 返回 false 可以取消导航
// 返回路由名称或路由对象可以重定向
})
// 配置全局后置守卫
router.afterEach((to, from) => {
console.log('导航后:', to, from)
})
// 导出钩子函数供页面使用
const { useRouter, useRoute } = router
export {
useRouter,
useRoute,
router
}
3. 在页面中使用
基本路由跳转
<script setup lang="ts">
import { useRouter } from '@/router'
const { push } = useRouter()
// 简单跳转(类型安全)
const goToHome = () => {
push('home')
}
// 带查询参数跳转
const goToDetail = () => {
push({
path: 'detail',
query: {
id: '123',
name: 'Product'
}
})
}
// 带回调的跳转
const goToProfile = () => {
push('profile', {
success: (result) => {
console.log('跳转成功,handler 返回:', result)
},
fail: (error) => {
console.error('跳转失败:', error)
}
})
}
</script>
页面关闭策略
// 默认: navigateTo - 保留当前页面
push({
path: 'detail'
})
// redirectTo - 关闭当前页面
push({
path: 'login'
close: 'current'
})
// reLaunch - 关闭所有页面
push({
path: 'index',
close: 'all'
})
获取当前路由信息
<script setup lang="ts">
import { useRoute } from '@/router'
const route = useRoute()
// 访问路由信息
console.log('当前路由名称:', route.name)
console.log('路由元信息:', route.meta)
console.log('查询参数:', route.query)
console.log('Handler 返回值:', route.handlerResult)
</script>
<template>
<view>
<text>当前页面: {{ route.name }}</text>
<text>参数 ID: {{ route.query.id }}</text>
</view>
</template>
🔧 高级功能
导航守卫
全局前置守卫 (beforeEach)
router.beforeEach((to, from) => {
console.log(`从 ${from.name} 跳转到 ${to.name}`)
// 权限检查示例
if (to.meta?.requireAuth && !isLoggedIn()) {
// 重定向到登录页
return 'login'
}
// 返回 false 取消导航
if (someCondition) {
return false
}
// 不返回或返回 true 继续导航
})
全局后置守卫 (afterEach)
router.afterEach((to, from) => {
// 页面访问统计
analytics.track('page_view', {
from: from.name,
to: to.name,
timestamp: Date.now()
})
// 设置页面标题
if (to.meta?.title) {
uni.setNavigationBarTitle({ title: to.meta.title })
}
})
守卫返回值
undefined或true: 继续导航false: 取消导航- 路由名称字符串: 重定向到指定路由
- 路由对象: 重定向到指定路由并携带参数
router.beforeEach((to, from) => {
// 简单重定向
if (needRedirect) {
return 'home'
}
// 带参数重定向
if (needRedirectWithParams) {
return {
path: 'detail',
query: { id: '123' }
}
}
})
路由处理函数 (Handler)
Handler 函数允许你在路由跳转时执行自定义逻辑,例如数据预加载、权限验证、埋点上报等。
注册 Handler
import { router } from '@/router'
// 数据预加载示例
router.register('productDetail', async (payload) => {
const { query } = payload
const productId = query.id
// 预加载商品数据
const product = await fetchProduct(productId)
// 返回的数据可在目标页面通过 route.handlerResult 获取
return product
})
// 权限检查示例
router.register('adminPanel', async (payload) => {
const user = await getCurrentUser()
if (!user.isAdmin) {
throw new Error('无权限访问管理面板')
}
return { allowed: true }
})
// 埋点上报示例
router.register('orderList', async (payload) => {
analytics.track('page_view', {
page: 'orderList',
timestamp: Date.now(),
...payload.query
})
})
获取 Handler 返回值
<script setup lang="ts">
import { useRoute } from '@/router'
const route = useRoute()
// 获取 handler 返回的数据
const product = route.handlerResult as Product
onMounted(() => {
if (product) {
console.log('预加载的商品数据:', product)
}
})
</script>
动态管理 Handler
// 检查是否已注册
if (router.has('productDetail')) {
console.log('已注册 productDetail handler')
}
// 注销 handler(返回取消函数)
const unregister = router.register('temp', async () => {
// 临时逻辑
})
// 稍后移除
unregister()
// 或直接移除
router.unregister('temp')
路由元信息 (Meta)
路由元信息从 pages.json 自动提取,包含以下字段:
interface RouteMeta {
/** 页面路径 */
url: string
/** 页面标题 */
navigationBarTitleText?: string
/** 是否为 tabBar 页面 */
isTabBar?: boolean
/** 页面唯一标识 */
name: string
/** 页面样式配置 */
style?: Record<string, any>
}
在 pages.json 中配置的页面样式会自动映射到 meta:
{
"pages": [
{
"path": "pages/home/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
}
]
}
访问元信息:
const route = useRoute()
console.log(route.meta?.navigationBarTitleText) // "首页"
console.log(route.meta?.isTabBar) // true/false
📝 API 参考
createRouter
创建 router 实例。
function createRouter<TName extends string>(
routes?: PagesConfig
): Router<TName>
参数:
routes: pages.json 配置对象(可选)
返回: Router 实例
Router 实例方法
register
注册路由处理函数。
register(name: TName, handler: RouteHandler): () => void
参数:
name: 路由名称handler: 处理函数,接收 payload,可返回任意值或 Promise
返回: 取消注册的函数
unregister
移除已注册的处理函数。
unregister(name: TName): boolean
返回: 是否成功移除
has
检查是否已注册处理函数。
has(name: TName): boolean
beforeEach
添加全局前置守卫。
beforeEach(guard: NavigationGuard<TName>): () => void
返回: 移除守卫的函数
afterEach
添加全局后置守卫。
afterEach(guard: NavigationGuard<TName>): () => void
返回: 移除守卫的函数
useRouter
返回路由操作钩子。
useRouter(): RouterHookResult<TName>
返回对象:
push: 类型安全的路由跳转函数
useRoute
返回当前路由信息。
useRoute(): RouteInfo<TName>
返回对象:
name: 当前路由名称meta: 路由元信息query: 查询参数handlerResult: Handler 返回值
useRouter 返回的方法
push
类型安全的路由跳转。
push(
data: TName | RouterParams<TName>,
callbacks?: {
success?: (result?: unknown) => void
fail?: (error?: any) => void
}
): Promise<void>
参数:
data: 路由名称字符串或路由参数对象callbacks: 可选的成功/失败回调
RouterParams 对象:
interface RouterParams<TPath extends string> {
path?: TPath // 路由名称
query?: Record<string, any> // 查询参数
close?: CloseTypes // 页面关闭策略
success?: (result?: unknown) => void // 成功回调
fail?: (error?: any) => void // 失败回调
}
CloseTypes 枚举
页面关闭策略。
enum CloseTypes {
default = 'default', // navigateTo - 保留当前页面
current = 'current', // redirectTo - 关闭当前页面
all = 'all' // reLaunch - 关闭所有页面
}
routeTypesPlugin
Vite 插件,自动生成路由类型。
function routeTypesPlugin(dts: string): Plugin
参数:
dts: 类型文件输出路径
示例:
routeTypesPlugin('./types/auto-page.d.ts')
生成的类型文件示例:
export type ENHANCE_ROUTE_PATH =
| 'demo'
| 'home'
| 'index'
| 'profile'
🎯 完整示例
示例 1:电商应用
// router/index.ts
import { createRouter } from 'uni-router-enhance'
import pagesJson from '../pages.json'
import type { ENHANCE_ROUTE_PATH } from '../../types/auto-page.d.ts'
const router = createRouter<ENHANCE_ROUTE_PATH>(pagesJson)
// 全局登录检查
router.beforeEach((to, from) => {
const needAuth = ['profile', 'order', 'cart'].includes(to.name)
if (needAuth && !isLoggedIn()) {
uni.showToast({ title: '请先登录', icon: 'none' })
return 'login'
}
})
// 商品详情页数据预加载
router.register('productDetail', async (payload) => {
const { query } = payload
const product = await fetchProduct(query.id)
return product
})
// 订单列表页权限检查
router.register('orderList', async () => {
const user = await getCurrentUser()
if (!user.hasOrders) {
throw new Error('暂无订单权限')
}
})
export const { useRouter, useRoute } = router
示例 2:商品详情页
<script setup lang="ts">
import { useRoute } from '@/router'
// 获取路由信息
const route = useRoute()
// 从 handler 获取预加载的数据
const product = computed(() => route.handlerResult as Product)
onLoad(() => {
console.log('页面参数:', route.query)
console.log('预加载数据:', product.value)
})
</script>
<template>
<view class="product-detail">
<image :src="product?.image" />
<text>{{ product?.name }}</text>
<text>¥{{ product?.price }}</text>
</view>
</template>
示例 3:商品列表页
<script setup lang="ts">
import { useRouter } from '@/router'
const { push } = useRouter()
const products = ref([])
const goToDetail = (productId: string) => {
push({
path: 'productDetail',
query: { id: productId },
success: () => {
console.log('跳转成功')
},
fail: (error) => {
uni.showToast({ title: error.message, icon: 'none' })
}
})
}
</script>
<template>
<view>
<view
v-for="item in products"
:key="item.id"
@click="goToDetail(item.id)"
>
{{ item.name }}
</view>
</view>
</template>
🔍 TypeScript 支持
本库完全使用 TypeScript 编写,提供完整的类型定义。
自动类型推断
// ✅ 类型安全 - 路由名称会被自动检查
push('home')
// ❌ 类型错误 - 不存在的路由
push('nonexistent')
// ✅ 查询参数类型安全
push({
path: 'detail',
query: {
id: '123',
tab: 'info'
}
})
自定义类型
// 定义查询参数类型
interface ProductDetailQuery {
id: string
from?: 'list' | 'search'
}
// 在 handler 中使用
router.register('productDetail', async (payload) => {
const query = payload.query as ProductDetailQuery
console.log(query.id, query.from)
})
⚠️ 注意事项
-
TabBar 页面限制
- TabBar 页面只能使用
uni.switchTab跳转 - 跳转到 TabBar 页面时,query 参数会被忽略
- TabBar 页面只能使用
-
路由名称提取规则
- 路由名称从页面路径的第二段提取
- 例如:
pages/home/index→ 路由名称为home - 分包路径:
subpackage/detail/index→ 路由名称为detail
-
Handler 执行时机
- Handler 在导航守卫之后、页面跳转之前执行
- Handler 抛出错误会阻止页面跳转
- Handler 返回
false会取消导航
-
缓存清理
- 页面缓存在跳转失败时会自动清理
- 建议在页面
onLoad后及时获取缓存数据
🤝 贡献
欢迎提交 Issue 和 Pull Request!
📄 License
MIT License
Made with ❤️ for uni-app developers

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 80
赞赏 0
下载 10988170
赞赏 1800
赞赏
京公网安备:11010802035340号