uni-router:现代化uni-app路由解决方案

0 阅读15分钟

本文基于 v1.4.0 版本,全面介绍 @meng-xi/uni-router 的设计理念与完整功能。

为什么需要 uni-router?

uni-app 原生路由系统基于 pages.json 静态配置,导航通过 uni.navigateTo / uni.redirectTo / uni.reLaunch / uni.navigateBack 等 API 直接调用,缺少以下关键能力:

  • 无路由守卫:无法在导航前进行权限校验、登录检查等拦截
  • 无命名路由:必须硬编码路径字符串,重构时容易遗漏
  • 无路由元信息:无法为路由附加标题、权限标记等结构化数据
  • 无错误体系:导航失败时只能通过回调获取,缺乏统一的错误处理机制
  • 无状态同步:浏览器后退、物理返回键等场景下路由状态可能不一致
  • 无页面间通信:无法在导航时建立页面间的事件通道

@meng-xi/uni-router 的目标是在 uni-app 的静态页面模型上,提供一套 vue-router 风格的路由管理方案,让开发者在 uni-app 中也能享受现代化的路由开发体验。


核心设计理念

不替代 pages.json,而是与之配合

uni-router 不替代 pages.json。页面注册仍由 pages.json 负责,uni-router 在此基础上提供路由导航、守卫、元信息等增强能力。这种设计确保了:

  • 完全兼容 uni-app 的页面管理机制
  • 不影响 pages.json 的条件编译等原生能力
  • 可以渐进式引入,无需改造现有项目

基于 uni-app 原生 API 实现

所有导航操作最终通过 uni.navigateTo / uni.redirectTo / uni.switchTab / uni.reLaunch / uni.navigateBack 执行,不绕过 uni-app 的页面管理机制,确保跨平台行为一致。


功能全景

一、路由导航

push — 导航到新页面

// 路径字符串
await router.push('/pages/about/about')

// 路径对象 + 查询参数
await router.push({ path: '/pages/about/about', query: { id: '1' } })

// 命名路由
await router.push({ name: 'about' })

// 带动画参数(仅 App 端生效)
await router.push({ path: '/pages/about/about', animation: { type: 'slide-in-bottom', duration: 500 } })

// 带页面间通信
const result = await router.push({
	path: '/pages/about/about',
	events: {
		// 监听目标页面通过 eventChannel.emit 发送的事件
		receiveData: (data) => { console.log('收到数据:', data) }
	}
})
// 通过 eventChannel 向目标页面发送事件
result.eventChannel?.emit('fromOpener', { msg: '你好' })

push 自动根据 meta.isTab 选择 uni.navigateTo(普通页面)或 uni.switchTab(TabBar 页面),开发者无需手动判断。

push 返回 NavigationResult,包含目标路由位置和可选的 eventChannel,用于页面间双向通信。

replace — 替换当前页面

await router.replace('/pages/login/login')
await router.replace({ name: 'home' })

对应 uni.redirectTo。替换 TabBar 页面时自动切换为 uni.switchTab(会关闭所有非 Tab 页面)。

relaunch — 关闭所有页面并打开目标页面

// 路径字符串
await router.relaunch('/pages/index/index')

// 命名路由 + 查询参数
await router.relaunch({ name: 'login', query: { redirect: '/about' } })

对应 uni.reLaunch,常用于:

  • 退出登录后跳转登录页
  • 从深层页面返回首页
  • 重置整个页面栈

设计细节

  • TabBar 页面自动切换为 uni.switchTab
  • uni.reLaunch 不支持动画参数,传入时输出警告
  • 不进行重复导航检测(清栈场景下目标页面可能就是当前页面)
  • 走完整守卫链(beforeEach → beforeEnter → beforeResolve → afterEach)

back — 返回上一页

await router.back() // 返回上一页
await router.back(2) // 返回两级
await router.back(1, { type: 'slide-out-left' }) // 指定动画

back() 执行完整的守卫链,守卫可以中止或重定向返回操作。若未指定动画参数,将使用目标页面的 meta.animation 作为默认动画。

重复导航检测

push 到当前页面时自动拒绝并抛出 NAVIGATION_DUPLICATED 错误,避免重复入栈。

注意:relaunch 不进行重复导航检测。因为清栈场景下目标页面可能就是当前页面(如"返回首页"),拒绝此类导航没有意义。

并发导航排队

多次并发导航自动排队,前一次完成后再执行下一次,避免页面栈混乱。


二、页面间通信(EventChannel)

v1.4.0 新增基于 uni.navigateTo 的 EventChannel 机制,实现页面间双向通信。

什么是 EventChannel?

EventChannel 是 uni-app 提供的页面间通信通道,允许发起导航的页面和被打开的页面通过事件机制互相发送数据。这在以下场景中非常有用:

  • 打开详情页时传递初始数据
  • 子页面操作完成后通知父页面刷新
  • 表单页提交结果回传到列表页

编程式导航通信

发起页 — 通过 push 的 events 参数和返回值通信

// 发起页
const result = await router.push({
	path: '/pages/detail/detail',
	query: { id: '1' },
	events: {
		// 监听目标页面 emit 的事件
		acceptData: (data) => {
			console.log('收到详情页数据:', data)
		},
		// 监听详情页的编辑完成通知
		editComplete: (data) => {
			console.log('编辑完成:', data)
			// 刷新列表等操作
		}
	}
})

// 通过 eventChannel 向目标页面发送事件
result.eventChannel?.emit('initData', { msg: '来自发起页的初始数据' })

目标页 — 通过 getOpenerEventChannel 接收和回复

// 目标页(detail)
export default {
	onLoad() {
		const eventChannel = this.getOpenerEventChannel()

		// 监听发起页发来的事件
		eventChannel.on('initData', (data) => {
			console.log('收到初始数据:', data)
		})

		// 向发起页发送数据
		eventChannel.emit('acceptData', { msg: '详情页已加载' })
	},
	methods: {
		onSave() {
			const eventChannel = this.getOpenerEventChannel()
			// 通知发起页编辑完成
			eventChannel.emit('editComplete', { id: 1, action: 'saved' })
		}
	}
}

声明式导航通信(RouterLink)

<template>
	<mxuni-router
		:to="{ path: '/pages/detail/detail', query: { id: '1' } }"
		:events="{ acceptData: (data) => onAcceptData(data) }"
		@navigated="onNavigated"
		@error="onNavError"
	>
		<view>跳转到详情页</view>
	</mxuni-router>
</template>

<script setup>
function onAcceptData(data) {
	console.log('收到详情页数据:', data)
}

function onNavigated(eventChannel) {
	// 导航成功后,通过 eventChannel 向目标页面发送事件
	eventChannel?.emit('initData', { msg: '来自 RouterLink 的初始数据' })
}

function onNavError(error) {
	console.log('导航失败:', error.code)
}
</script>

EventChannel 接口

interface EventChannel {
	/** 监听事件,每次 emit 都会触发 */
	on(event: string, callback: (...args: any[]) => void): EventChannel
	/** 监听事件,仅触发一次后自动移除 */
	once(event: string, callback: (...args: any[]) => void): EventChannel
	/** 取消监听事件 */
	off(event: string, callback?: (...args: any[]) => void): EventChannel
	/** 触发事件 */
	emit(event: string, ...args: any[]): EventChannel
}

通信限制

导航方式对应 uni API支持 EventChannel说明
pushuni.navigateTo返回 NavigationResult.eventChannel
replaceuni.redirectTo传入 events 时输出警告并忽略
relaunchuni.reLaunch传入 events 时输出警告并忽略
backuni.navigateBack返回操作不创建新页面,无通信通道
TabBar 页面uni.switchTab传入 events 时输出警告并忽略

三、路由守卫

路由守卫是 uni-router 最核心的能力,提供完整的导航拦截机制。

全局前置守卫 — beforeEach

在每次导航前执行,常用于登录验证:

router.beforeEach((to, from, next) => {
	if (to.meta.requireAuth && !isLoggedIn()) {
		next({ name: 'login', query: { redirect: to.fullPath } })
	} else {
		next()
	}
})

全局解析守卫 — beforeResolve

在所有前置守卫和路由独享守卫完成后执行,适合需要确保所有守卫都已通过的场景:

router.beforeResolve((to, from, next) => {
	// 所有前置守卫已通过,导航即将执行
	next()
})

全局后置钩子 — afterEach

在导航完成后执行,不影响导航结果,适合埋点、标题设置等操作:

router.afterEach((to, from) => {
	if (to.meta.title) {
		uni.setNavigationBarTitle({ title: to.meta.title as string })
	}
})

路由独享守卫 — beforeEnter

在路由配置中定义,仅对该路由生效:

const routes = [
	{
		path: 'pages/admin/admin',
		name: 'admin',
		meta: { requireAuth: true },
		beforeEnter: (to, from, next) => {
			if (isAdmin()) next()
			else next({ name: 'forbidden' })
		}
	}
]

支持数组形式,按顺序依次执行:

const routes = [
	{
		path: 'pages/admin/admin',
		name: 'admin',
		beforeEnter: [checkAuth, checkAdmin]
	}
]

守卫执行顺序

beforeEach → beforeEnter → beforeResolve → 导航执行 → afterEach

守卫重定向

守卫中调用 next(location) 可重定向到其他路由,支持多级重定向(最大深度 10):

router.beforeEach((to, from, next) => {
	if (to.meta.requireAuth && !isLoggedIn()) {
		next({ name: 'login' }) // 重定向到登录页
	} else {
		next()
	}
})

守卫超时保护

通过 guardTimeout 配置项(默认 10000ms),防止守卫未调用 next() 导致导航永久挂起:

const router = createRouter({
	routes,
	guardTimeout: 15000 // 15 秒超时
})

守卫注册返回移除函数

所有守卫注册函数均返回一个移除函数,支持动态注册和注销:

const removeGuard = router.beforeEach((to, from, next) => {
	// 临时守卫逻辑
	next()
})

// 不再需要时移除
removeGuard()

四、命名路由

通过 name 字段进行导航,避免硬编码路径字符串:

// 路由配置
const routes = [
	{ path: 'pages/index/index', name: 'home', meta: { isTab: true } },
	{ path: 'pages/about/about', name: 'about', meta: { title: '关于' } }
]

// 导航时使用名称
await router.push({ name: 'about', query: { id: '1' } })

配合 @meng-xi/vite-plugin 自动生成的类型声明,路由名称可获得 TypeScript 自动补全和类型检查。


五、路由元信息

meta 字段支持页面标题、权限标记、TabBar 标识、导航动画等自定义数据:

interface RouteMeta {
	title?: string // 页面标题
	isTab?: boolean // 是否为 TabBar 页面
	requireAuth?: boolean // 是否需要登录认证
	animation?: NavigationAnimation // 默认导航动画(仅 App 端)
	[key: string]: unknown // 自定义扩展字段
}

使用示例:

const routes = [
	{ path: 'pages/index/index', name: 'home', meta: { isTab: true, title: '首页' } },
	{ path: 'pages/about/about', name: 'about', meta: { animation: { type: 'fade-in' } } },
	{ path: 'pages/admin/admin', name: 'admin', meta: { requireAuth: true } }
]

六、导航动画

完整的页面切换动画支持,仅 App 端生效,其他平台自动忽略。

NavigationAnimation 接口

interface NavigationAnimation {
	type: UniAnimationType // 动画类型
	duration?: number // 持续时间(ms),默认 300
}

UniAnimationType — 完整动画类型

显示动画(navigateTo)关闭动画(navigateBack)
slide-in-rightslide-out-right
slide-in-leftslide-out-left
slide-in-topslide-out-top
slide-in-bottomslide-out-bottom
fade-infade-out
zoom-outzoom-in
zoom-fade-outzoom-fade-in
pop-inpop-out
auto / noneauto / none

三种使用方式

1. 导航时传入动画参数

await router.push({ path: '/pages/about/about', animation: { type: 'slide-in-bottom' } })
await router.back(1, { type: 'slide-out-left', duration: 500 })

2. 路由级默认动画(meta.animation)

const routes = [{ path: 'pages/about/about', name: 'about', meta: { animation: { type: 'fade-in' } } }]

3. RouterLink 声明式动画

<RouterLink to="/pages/about/about" :animation="{ type: 'slide-in-bottom' }">
  底部滑入
</RouterLink>

动画优先级

push/replace/back 调用时传入 > meta.animation > uni 默认值

各导航方式对动画的支持

导航方式对应 uni API支持动画说明
pushuni.navigateTo传入 animationType/duration
replaceuni.redirectTouni.redirectTo 不支持动画参数
relaunchuni.reLaunchuni.reLaunch 不支持动画参数
backuni.navigateBack传入 animationType/duration
TabBar 页面uni.switchTabuni.switchTab 不支持动画参数

传入动画参数但不支持时,路由器会输出 console.warn 提醒开发者。


七、uni API 拦截

通过 interceptUniApi 选项拦截原生导航 API,确保路由守卫始终生效:

const router = createRouter({
	routes,
	interceptUniApi: true // 拦截 uni.navigateTo 等原生 API
})

启用后,以下调用将被拦截并转由路由器处理:

// 这两种方式等价,都会经过守卫链
uni.navigateTo({ url: '/pages/about/about' })
router.push('/pages/about/about')

拦截原理

  • 通过 uni.addInterceptor 注册拦截器
  • 路由器内部发起的 API 调用通过计数器标记放行,避免重复执行守卫
  • 外部调用被拦截后,阻止原始 API 执行,转由 router.push/replace/relaunch/back 执行完整守卫链
  • 低版本小程序基础库兼容:修改 args.url 为空字符串,防止忽略返回值继续执行

拦截范围

API拦截后行为
uni.navigateTorouter.push
uni.redirectTorouter.replace
uni.switchTabrouter.push
uni.reLaunchrouter.relaunch
uni.navigateBackrouter.back

八、组合式 API

useRouter — 获取路由器实例

import { useRouter } from '@meng-xi/uni-router'

const router = useRouter()
await router.push('/pages/about/about')

必须在 Vue 组件的 setup() 中调用,通过 Vue 的 inject 机制获取路由器实例。

useRoute — 获取响应式路由位置

import { useRoute } from '@meng-xi/uni-router'

const route = useRoute()
// route 是 Ref<RouteLocation>,路由变化时自动更新
console.log(route.value.path)
console.log(route.value.query)

同一 router 实例共享同一个响应式 ref,通过 WeakMap 缓存避免重复创建。

Options API — routerrouter 和 route

在 Options API 组件中,可通过 this.$routerthis.$route 访问路由器:

export default {
	methods: {
		goToAbout() {
			this.$router.push('/pages/about/about')
		}
	},
	computed: {
		currentPath() {
			return this.$route.path
		}
	}
}

为避免与 uni-app H5 内置的 vue-router 冲突,$router$route 仅在未被定义时设置。


九、RouterLink 组件

基于 uni-app navigator 封装的声明式导航组件:

<template>
	<!-- 路径跳转 -->
	<RouterLink to="/pages/about/about">关于页面</RouterLink>

	<!-- 命名路由 + 替换模式 -->
	<RouterLink :to="{ name: 'about' }" replace>替换导航</RouterLink>

	<!-- relaunch 模式(关闭所有页面并打开目标页面) -->
	<RouterLink to="/pages/index/index" relaunch>返回首页</RouterLink>

	<!-- 带动画参数 -->
	<RouterLink to="/pages/about/about" :animation="{ type: 'fade-in' }">淡入动画</RouterLink>

	<!-- 带页面间通信 -->
	<RouterLink
		:to="{ path: '/pages/detail/detail', query: { id: '1' } }"
		:events="{ acceptData: (data) => console.log(data) }"
		@navigated="onNavigated"
		@error="onNavError"
	>
		跳转并通信
	</RouterLink>
</template>

<script setup>
import { RouterLink } from '@meng-xi/uni-router/components/RouterLink.vue'

function onNavigated(eventChannel) {
	// 向目标页面发送事件
	eventChannel?.emit('initData', { msg: '来自 RouterLink' })
}

function onNavError(error) {
	console.log('导航失败:', error.code)
}
</script>

Props

Prop类型默认值说明
toRouteLocationRaw-目标路由位置
replacebooleanfalse是否使用替换模式导航
relaunchbooleanfalse是否使用 relaunch 模式导航,优先级高于 replace
animationNavigationAnimationundefined导航动画(仅 App 端)
eventsEventListenersundefined页面间通信事件监听器(仅 push 时生效)
hoverClassstring'navigator-hover'按下时的样式类
hoverStopPropagationbooleanfalse阻止祖先节点点击态
hoverStartTimenumber50按住后出现点击态时间
hoverStayTimenumber600松开后点击态保留时间

Events

事件参数说明
navigatedEventChannel | void导航成功后触发,参数为 eventChannel 实例
errorNavigationFailure导航失败时触发

十、路由状态同步

当页面通过浏览器后退、物理返回键等非路由器方式切换时,路由器的 currentRoute 可能与实际页面不同步。syncRoute() 方法从 uni-app 页面栈中读取当前页面信息并更新路由状态:

// 在每个页面的 onShow 生命周期中调用
import { onShow } from '@dcloudio/uni-app'
import { useRouter } from '@meng-xi/uni-router'

const router = useRouter()

onShow(() => {
	router.syncRoute()
})

onRouteChange — 路由变化监听

注册路由状态变化监听器,导航完成和状态同步时都会触发:

router.onRouteChange((to, from) => {
	console.log(`路由变化: ${from.path}${to.path}`)
})

afterEach 不同,onRouteChange 也会捕获 syncRoute() 触发的状态变化。


十一、错误处理

完整的错误体系

// RouterError — 路由错误基类
class RouterError extends Error {
	readonly code: RouterErrorCode
}

// NavigationFailure — 导航失败,包含来源和目标信息
class NavigationFailure extends RouterError {
	readonly to: RouteLocation
	readonly from: RouteLocation
	readonly cause?: unknown
}

错误码

错误码说明
NAVIGATION_ABORTED导航被守卫中止或守卫超时
NAVIGATION_CANCELLED导航被取消(守卫异常或重定向超限)
NAVIGATION_DUPLICATED重复导航到当前位置
ROUTE_NOT_FOUND未找到匹配的路由
NAVIGATION_API_ERRORuni 导航 API 调用失败
SETUP_ERROR路由器初始化或使用方式错误

全局错误捕获

router.onError((error, to, from) => {
	if (error.code === 'NAVIGATION_ABORTED') {
		console.log('导航被中止')
	}
})

onError 返回移除函数,支持动态注销:

const removeHandler = router.onError((error, to, from) => {
	// 错误处理
})
removeHandler() // 移除此处理器

十二、TypeScript 类型提示

配合 @meng-xi/vite-plugin 自动生成的类型声明,为路由导航提供类型安全:

// 路由名称自动补全
router.push({ name: 'pagesIndexIndex' }) // ✅ 自动补全
router.push({ name: 'invalidName' }) // ❌ 类型错误

// 路径自动补全
router.push({ path: '/pages/index/index' }) // ✅ 自动补全
router.push({ path: '/invalid/path' }) // ❌ 类型错误

通过模块增强(module augmentation)填充 RouteNameMap 接口即可启用:

declare module '@meng-xi/uni-router' {
	interface RouteNameMap {
		pagesIndexIndex: { path: '/pages/index/index'; meta: { title: string; isTab: true } }
		pagesAboutAbout: { path: '/pages/about/about'; meta: { title: string } }
	}
}

API 速查

核心

API说明
createRouter(options)创建路由器实例
useRouter()获取路由器实例(组合式 API)
useRoute()获取响应式路由位置(组合式 API)
RouterLink声明式导航组件

Router 实例方法

方法说明返回值
router.push(location)导航到新页面Promise<NavigationResult>
router.replace(location)替换当前页面Promise<RouteLocation>
router.relaunch(location)关闭所有页面并打开目标页面Promise<RouteLocation>
router.back(delta?, animation?)返回上一页或多级页面Promise<void>
router.beforeEach(guard)注册全局前置守卫() => void 移除函数
router.beforeResolve(guard)注册全局解析守卫() => void 移除函数
router.afterEach(guard)注册全局后置钩子() => void 移除函数
router.onRouteChange(listener)注册路由变化监听器() => void 移除函数
router.onError(handler)注册错误处理回调() => void 移除函数
router.syncRoute()同步路由状态与页面栈void
router.resolve(location)解析路由位置(不导航)RouteLocation
router.getRoutes()获取所有路由配置RouteConfig[]
router.hasRoute(name)检查路由是否存在boolean

RouterOptions

选项类型默认值说明
routesRouteConfig[]-路由配置列表
strictbooleantrue严格模式,未匹配路由时抛出异常
interceptUniApibooleanfalse拦截原生导航 API
guardTimeoutnumber10000守卫超时时间(ms)

RouteConfig

字段类型说明
pathstring页面路径,需与 pages.json 一致
namestring路由名称,用于命名路由导航
metaRouteMeta路由元信息
beforeEnterNavigationGuard | NavigationGuard[]路由独享守卫

NavigationResult

push() 的返回值,继承 RouteLocation,额外包含 eventChannel

字段类型说明
pathstring规范化后的路径
namestring | undefined路由名称
metaRouteMeta路由元信息
queryRecord<string, string>查询参数
fullPathstring完整路径(含查询参数)
eventChannelEventChannel | undefined页面间通信通道(仅 push)

与 pages.json 的关系

职责pages.jsonuni-router
页面注册必须声明不负责
路由导航uni.navigateTopush / replace / relaunch / back
路由守卫不支持beforeEach
路由元信息不支持meta 字段
命名路由不支持name 字段
导航动画手动传参animation + meta.animation
页面间通信手动管理events + eventChannel

快速开始

1. 安装

pnpm add @meng-xi/uni-router

2. 配置路由

// src/router.config.ts
import type { RouteConfig } from '@meng-xi/uni-router'

const routes: RouteConfig[] = [
	{ path: 'pages/index/index', name: 'home', meta: { isTab: true, title: '首页' } },
	{ path: 'pages/about/about', name: 'about', meta: { title: '关于' } },
	{ path: 'pages/login/login', name: 'login', meta: { title: '登录' } },
	{ path: 'pages/admin/admin', name: 'admin', meta: { requireAuth: true } }
]

export default routes

3. 创建路由器

// src/main.ts
import { createSSRApp } from 'vue'
import { createRouter } from '@meng-xi/uni-router'
import routes from './router.config'
import App from './App.vue'

const router = createRouter({
	routes,
	strict: true,
	interceptUniApi: true,
	guardTimeout: 15000
})

// 注册全局守卫
router.beforeEach((to, from, next) => {
	if (to.meta.requireAuth && !isLoggedIn()) {
		next({ name: 'login' })
	} else {
		next()
	}
})

router.afterEach(to => {
	if (to.meta.title) {
		uni.setNavigationBarTitle({ title: to.meta.title as string })
	}
})

export function createApp() {
	const app = createSSRApp(App)
	app.use(router)
	return { app }
}

4. 在页面中使用

<template>
	<view>
		<text>当前路径: {{ route.path }}</text>
		<button @click="goAbout">跳转关于</button>
		<button @click="goAboutWithEvent">跳转并通信</button>
		<button @click="goBack">返回</button>
	</view>
</template>

<script setup>
import { useRouter, useRoute } from '@meng-xi/uni-router'

const router = useRouter()
const route = useRoute()

async function goAbout() {
	try {
		await router.push({ name: 'about', query: { from: 'home' } })
	} catch (e) {
		console.log('导航失败:', e.code)
	}
}

async function goAboutWithEvent() {
	const result = await router.push({
		path: '/pages/about/about',
		events: {
			replyFromAbout: (data) => {
				console.log('收到关于页回复:', data)
			}
		}
	})
	// 向关于页发送消息
	result.eventChannel?.emit('fromHome', { msg: '你好,关于页!' })
}

async function goBack() {
	await router.back()
}
</script>

平台兼容性

平台支持情况
uni-app (Vue 3)✅ 完全支持
uni-app H5 (Safari / Chrome)✅ 完全支持
uni-app App (Android / iOS)✅ 完全支持(动画仅 App 端生效)
uni-app 小程序(微信/支付宝/百度/字节等)✅ 完全支持
uni-app x Web✅ 支持
uni-app x 小程序✅ 支持
uni-app x App (Android / iOS / Harmony)❌ 不支持(无 JS 引擎,需 UTS 重写)

版本演进

版本核心新增能力
v1.0.0路由导航、守卫、命名路由、元信息、组合式 API、拦截器
v1.1.0守卫超时保护、路由变化监听、RouterLink @error
v1.2.0导航动画(NavigationAnimation / meta.animation)
v1.3.0relaunch 导航方式、RouterLink relaunch prop
v1.4.0EventChannel 页面间通信、RouterLink events/@navigated

总结

@meng-xi/uni-router 为 uni-app 开发者提供了一套完整的路由管理方案:

  • vue-router 风格 API:零学习成本,上手即用
  • 完整的守卫体系:beforeEach / beforeResolve / afterEach / beforeEnter,支持重定向和超时保护
  • 页面间通信:EventChannel 双向通信,编程式和声明式均支持
  • 导航动画:三种使用方式,优先级清晰,仅 App 端生效
  • uni API 拦截:确保守卫始终生效,无论通过何种方式发起导航
  • TypeScript 类型提示:路由名称和路径自动补全
  • 错误处理体系:完整的错误码和全局错误捕获
  • 组合式 API:useRouter / useRoute,响应式路由状态
  • Options APIrouter/router / route 全局属性
  • 路由状态同步:处理浏览器后退、物理返回键等场景