更新记录

0.8.0(2026-09-27) 下载此版本

新增

  • 基于文件的路由生成插件(构建期 dev 工具,随路由库同包分发):
    • 页面就近声明 defineUniPage 宏(或 <route-config lang="jsonc|uts"> 自定义块),构建期自动生成 pages.json(含 tabBar / subPackages)与 routes.gen.uts 路由表,消除 path / title / tabBar / isTab 双份手工维护
    • 优先级链:宏 > 块 > 插件推导(titleFallback / tabBar 配置兜底),字段级合并
    • name 自动规范化:末段 camelCase → 冲突回退全路径 camelCase → 终极冲突按 errorStrategy(strict 抛错 / warn 告警)
    • beforeEnter / meta 扩展经宏声明(UTS 表达式原样注入生成文件,须自包含)
    • preserveRouteChanges(默认开启):重生成时保留你对路由文件的既有修改与自定义路由
    • pages.json 手写的非页面字段(globalStyle、uniIdRouter 等)重生成时合并保留
    • watch:页面新增/删除/修改 200ms 去抖串行重跑两阶段流水线
    • 生成 route-name.gen.d.ts(WEB 端 RouteNameMap 字面量类型)与 define-uni-page.d.ts(宏类型声明),均可关闭
  • 新增子路径导出 @meng-xi/unix-router/vite-plugin:vite / webpack 适配器(unplugin 打包内置,运行时零额外依赖),node/ 源码目录在 UTS 编译扫描范围外,主入口 UTS 编译不受影响
  • 插件拆分为三个独立实现(node/ 重组为 route-gen / pages-gen / routes-gen + shared 目录),可独立或组合注册、互不影响:
    • routeGen:页面文件 → pages.json + routes.gen.uts 全量流水线(行为与此前一致)
    • pagesGen:页面文件 → 仅 pages.json(含宏 dts),不触碰路由文件
    • routesGen:pages.json → 仅路由表,不触碰 pages.json;支持扩展声明文件 routes.ext.uts(path / name ↔ 显式 name / meta 扩展 / beforeEnter,函数原文注入;router.extensions 可改路径或 false 关闭)
    • 选项随插件拆分:公共选项(pagesJsonPath / watch / verbose / errorStrategy)+ pages 段 / router 段

修复

  • Android 云打包编译错误(UTS 强类型):
    • Promise.catch 回调参数类型由 any 调整为 any | null:UTS 的 any 编译为 Kotlin 非空 Any,无法匹配 UTSPromise.catch 要求可空回调参数的重载
    • isNavigationFailure 首参签名由 Error | null 放宽为 any | null(内部 instanceof 收窄),修复 .catch((e) => isNavigationFailure(e)) 链式用法编译失败
  • *H5 端 `uni.导航 API 编译类型警告**:WEB 端导航 options 收敛为统一桥接函数applyWebNavOptions(动态字段经as any桥接),消除uni.navigateTo` 等的编译警告,运行时行为不变
  • H5 端 router.push 崩溃:pickAnimation / toUniAnimation / pickEvents 对可选字段 === null 判断后直接取 .length / .size,H5(JS 运行时)缺省值是 undefined 导致 TypeError、导航中断;统一 ?? null 归一化后判断
  • App 端导航动画透传缺失:AnimationPlugin 此前 App 端实际未透传动画参数,现 uni.navigateTo / uni.navigateBack 具名 Options 携带 animationType / animationDuration(官方类型声明标注仅 App 支持:Android 4.18+ / iOS 4.25+ / HarmonyOS 4.61+);小程序端官方不支持动画字段,redirectTo / reLaunch / switchTab 官方 Options 无动画字段,均不携带

0.7.0(2026-09-20) 下载此版本

变更(破坏性)

  • 插件注册改为实例化:非蒸汽(原生 Kotlin/Swift)端不支持「对象字面量承载方法」,RouterPlugin 由 type 调整为 abstract class,内置插件改为 class ParamsPlugin extends RouterPlugin 实现,注册写法从 plugins: [ParamsPlugin] 变更为 plugins: [new ParamsPlugin()](Interceptor / Animation / Events 三个插件同理)

修复

  • 非蒸汽(原生)编译全链路兼容:
    • 含方法的对象字面量 class 化:RouteState / GuardManager / RouteMatcher / ParamsManager / PluginContext 均由「工厂返回对象字面量」重构为 class,消除 Kotlin 端被推断为 UTSJSONObject 导致的方法调用失效
    • 条件语句显式布尔化:全库移除 truthy 判断(if (x) → if (x != null)),符合 UTS 条件必须为布尔值的规范
    • uni.* 导航 options 跨端适配:App / 小程序使用无动画字段的对象字面量(匹配 NavigateToOptions 具名参数),H5 使用 UTSJSONObject 携带 animationType
    • 变参函数类型兼容:事件回调由 (...args: any[]) => any 调整为单参数 (data: any) => any(Kotlin 函数类型参数不支持 vararg / 修饰符)
    • 遍历与类型清理:移除 for..in + Object.prototype 遍历(改用 UTSJSONObject.keys())、清除 undefined 标识符与 Promise.reject 返回类型问题、显式可空参数
    • 页面层:模板绑定顶层函数改为本地包装函数(非蒸汽下端顶层函数以属性对象暴露);ucss 复合/后代选择器改为动态 class

0.6.0(2026-09-18) 下载此版本

新增

  • EventsPlugin 页面间事件通信插件(opt-in,plugins: [EventsPlugin]):
    • 对齐 uni-app 官方 navigateTo 的 events 语义:打开方 push 携带 events 监听表,被打开页通过 useOpenerEventChannel() 的 EventChannel emit 回传数据 / on 接收推送
    • 底层为自研 eventBus($on / $once / $off / $emit,按 id 移除监听),不受官方 uni.$on 版本门槛限制
    • 通道 key 经内部 __evt__ URL 查询串跨页桥接,状态同步时剔除(不暴露给用户);useOpenerEventChannel() 不依赖路由同步时机,onShow 内即可使用
    • 未注册插件却携带 events 的导航抛 PLUGIN_REQUIRED,明确引导
  • 新增导出:EventsPlugin / eventBus / useOpenerEventChannel
  • 新增类型:EventsMap;RawLocation / RouteLocationRaw 支持 events 可选字段
查看更多

平台兼容性

uni-app x(3.8.4)

Chrome Safari Android iOS 鸿蒙 微信小程序
√ √ √ √ √ √

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
√ √ √ √

ux-router

为 uni-app x 提供的、API 对标 vue-router 4 的路由管理库。以 UTS 源码(.uts)形式随 uni_modules 分发,由 uni-app x 编译链按平台现场编译(Web / 小程序 → JS,Android → Kotlin,iOS → Swift),无需预编译。

简介

uni-app x 原生提供 uni.navigateTo / redirectTo / reLaunch / navigateBack / switchTab,但当页面增多后「无路由表、无守卫、无统一路由状态、参数传递繁琐」成为痛点。ux-router 用一套与 vue-router 一致的 API 抹平这些差异,并提供登录鉴权、导航控制、参数传递等能力。

特性

  • vue-router 风格 API:createRouter、push / replace / relaunch / back,自动根据 meta.isTab 切换 switchTab
  • 路由匹配:path / name 双索引,字符串 / 对象 / 命名三种解析,strict 严格模式
  • 路由守卫:beforeEach / beforeResolve / afterEach / beforeEnter / 组件内守卫,支持重定向、守卫超时与重定向深度上限
  • 组合式 API:useRouter() / useRoute() / useLink(),响应式 currentRoute
  • 导航控制:重复导航自动拒绝(DUPLICATED)、并发导航自动排队
  • 错误体系:RouterError / NavigationFailure / UniNavigationApiError,RouterErrorCode 错误码,isNavigationFailure() 精准判断,onError 全局捕获
  • 冷启动守卫:guardRoute() 对 H5 直达 / 场景值 / deeplink 补执行守卫链,支持重定向与中止回调(onAbort)
  • 路由状态同步:页面 onShow 自动 syncRoute(),物理返回 / TabBar 切换等非路由器导航自动对齐
  • 基于文件的路由生成(构建期 dev 工具,opt-in):从 npm 包 @meng-xi/unix-router/vite-plugin(uni_modules 分发版随包附带 plugins/ 适配器)引入 vite 插件,页面就近声明 defineUniPage 宏,构建期自动生成 pages.json 与路由表 routes.gen.uts,消除 path / title / isTab 双份手工维护;提供 routeGen / pagesGen / routesGen 三个独立插件
  • 插件体系(opt-in,注册须实例化):
    • ParamsPlugin 页面参数传递:params(Map<string,string>)经 __params__ 关联存储跨页传递,键名不暴露明文
    • InterceptorPlugin uni API 拦截:interceptUniApi: true 时,直调 uni.navigateTo / switchTab 等原生导航也转入守卫链
    • AnimationPlugin 导航窗口动画:App 端透传原生 animationType / animationDuration(动画字段官方仅 App 支持,小程序端官方不支持、无动画),H5 端通过 WAAPI 播放进入 / 退出动画;支持全局默认(animation 选项)与单次覆盖
    • EventsPlugin 页面事件通信:对齐官方 navigateTo 的 events 语义,被打开页经 useOpenerEventChannel() 回传 / 接收数据

目录结构

ux-router/
├── package.json          # uni_modules 插件清单(id / displayName / 版本等)
├── changelog.md          # 更新日志
├── readme.md             # 本说明
├── plugins/              # 构建期文件路由 vite 插件适配器(JS 产物,routeGen / pagesGen / routesGen)
└── utssdk/               # UTS 源码(核心逻辑)
    ├── index.uts         # 公共入口
    ├── router/           # 路由器(createRouter 主实现)
    ├── matcher/          # 路由匹配
    ├── guard/            # 守卫管理
    ├── history/          # 页面栈适配
    ├── navigation/       # uni.* 导航封装
    ├── state/ store/     # 路由状态
    ├── composables/      # useRouter / useRoute / useLink / useOpenerEventChannel / 组件内守卫
    ├── plugins/          # 内置插件:params / interceptor / animation / events
    ├── components/       # RouterLink.uvue 声明式导航组件
    ├── errors/ enums/    # 错误与错误码
    ├── types/            # 类型定义
    ├── utils/            # path / query / params 工具
    └── constants/        # 常量

引入方式

本插件为 uni_modules 自包含,无需 npm 安装,直接 import 即可:

import { createRouter } from '@/uni_modules/ux-router/utssdk/index.uts'

快速开始

1. 定义路由配置

path 须与 pages.json 注册的页面路径一致:

import type { RouteConfig } from '@/uni_modules/ux-router/utssdk/index.uts'

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

2. 创建路由器

import { createRouter } from '@/uni_modules/ux-router/utssdk/index.uts'
import { routes } from './router.config'

export const router = createRouter({ routes, strict: true })

// 可选:按需注册插件(注册须实例化,0.7.0 起为破坏性变更)
// import { ParamsPlugin, InterceptorPlugin, AnimationPlugin, EventsPlugin } from '@/uni_modules/ux-router/utssdk/index.uts'
// export const router = createRouter({
//  routes,
//  plugins: [new ParamsPlugin(), new InterceptorPlugin(), new AnimationPlugin(), new EventsPlugin()]
// })

3. 安装到应用

// main.uts
import { createSSRApp } from 'vue'
import App from './App.uvue'
import { router } from './router'

export function createApp() {
    const app = createSSRApp(App)
    app.use(router) // provide 路由 + 注入全局 mixin(onShow 自动 syncRoute)
    return { app }
}

4. 页面内使用

<script setup lang="uts">
import { useRouter, useRoute } from '@/uni_modules/ux-router/utssdk/index.uts'

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

function go() {
    router.push({ name: 'about', query: new Map([['from', 'home']]) })
}
</script>

路由选项

createRouter 支持以下常用选项:

选项 类型 默认值 说明
routes RouteConfig[] - 路由配置,需与 pages.json 声明一致
strict boolean true 严格模式,未匹配的命名路由抛出 RouterError
guardTimeout number 10000 守卫超时(ms),超时警告并自动中止导航,设 0 关闭
readyTimeout number 0 就绪超时(ms),防止 await router.isReady() 挂起
plugins RouterPlugin[] - 可选插件列表,传入实例:[new ParamsPlugin()] / [new InterceptorPlugin()] / [new AnimationPlugin()] / [new EventsPlugin()]
paramsPersistent boolean false 是否默认将 params 持久化到 storage(需配合 ParamsPlugin)
interceptUniApi boolean false opt-in:拦截 uni.* 原生导航,使直调也走守卫链(运行时版本要求:Web 4.0 / 微信 4.41 / Android 3.97 / iOS 4.11 / Harmony 4.61,需配合 InterceptorPlugin)
animation NavigationAnimation - 全局默认导航动画 { type, duration }(需配合 AnimationPlugin 才生效)

路由导航

方法 对应原生 API 行为
router.push(location) uni.navigateTo / switchTab 保留当前页,推入新页
router.replace(location) uni.redirectTo / switchTab 替换当前页
router.relaunch(location) uni.reLaunch / switchTab 关闭所有页,打开目标
router.back(delta) uni.navigateBack 返回上一页或多级
await router.push({ name: 'about', query: new Map([['a', '1']]) })
await router.replace('/pages/detail/detail')
await router.relaunch('/pages/index/index')
await router.back()      // 返回一页
await router.back(2)     // 返回两级

目标为 meta.isTab 的路由会自动使用 uni.switchTab。

路由守卫

router.beforeEach((to, from) => {
    if (to.meta.requireAuth === true && !isLoggedIn()) {
        return { name: 'login', query: new Map([['redirect', to.fullPath]]) } // 重定向
    }
    return true // null / true 放行
})

router.afterEach((to, from, failure) => {
    console.log(`导航: ${from.fullPath} -> ${to.fullPath}`, failure?.message ?? '')
})

// 组件内离开守卫(返回 false 阻止离开)
import { onBeforeRouteLeave } from '@/uni_modules/ux-router/utssdk/index.uts'
onBeforeRouteLeave((to, from) => hasUnsavedChanges ? false : true)

守卫全集:beforeEach / beforeResolve / afterEach / beforeEnter / onBeforeRouteLeave / onBeforeRouteEnter / onBeforeRouteUpdate,以及冷启动补执行 guardRoute()。

冷启动(H5 直达 / 场景值 / deeplink)时页面已加载、守卫未执行,可补跑守卫链:

router.isReady().then(() => {
    router.guardRoute(undefined, {
        : () => router.relaunch('/pages/index/index') // 守卫中止时转跳安全页
    })
})

参数传递

  • query:URL 可见,适合少量、简单、可分享的数据
  • params:经 ParamsPlugin(__params__ 关联存储)跨页传递,键名不暴露明文,适合命名参数(需注册 plugins: [new ParamsPlugin()])

两者均为 Map<string,string>:

import { queryInt, queryBool } from '@/uni_modules/ux-router/utssdk/index.uts'

router.push({ name: 'detail', params: new Map([['id', '42'], ['from', '首页']]) })

// 目标页读取(Map API)
const route = useRoute()
const id = route.params.get('id') ?? ''   // "42"

// query 读取同样用 Map API,配合工具函数便捷解析
const from = route.query.get('utm') ?? ''   // query 用 .query.get
const idNum = queryInt(route.query, 'id', 0)     // 便捷解析数值
const flag  = queryBool(route.query, 'vip', false) // 便捷解析布尔

复杂对象请先 JSON.stringify,或改用全局状态 / uni.setStorageSync 承载。

组合式 API

  • useRouter():获取路由器实例
  • useRoute():响应式当前路由(脚本/模板直接访问字段,如 route.path / route.query.get())
  • useLink():声明式导航的响应式状态与触发(isActive / navigate 等),配套 RouterLink 组件直接使用
  • useOpenerEventChannel():获取打开方事件通道(需 EventsPlugin),不依赖路由同步时机,onShow 内即可使用

API 概览

分类 内容
创建 createRouter(options)
导航 push / replace / relaunch / back
守卫 beforeEach / beforeResolve / afterEach / beforeEnter
组合式 useRouter / useRoute / useLink / useOpenerEventChannel / onBeforeRouteLeave/Enter/Update
查询 getRoutes / hasRoute / resolve / currentRoute / isReady
同步/扩展 syncRoute / guardRoute / onError / onRouteChange
插件 ParamsPlugin / InterceptorPlugin / AnimationPlugin / EventsPlugin / eventBus(注册须实例化)
组件 RouterLink(声明式导航)
错误 RouterError / NavigationFailure / RouterErrorCode / isNavigationFailure

完整 API 与「从入门到精通」教程见仓库 packages/docs。

平台兼容性

  • Web / H5、微信小程序:编译为 JS
  • App-Android / App-HarmonyOS(VDOM / 蒸汽模式):编译为 Kotlin / JS(HarmonyOS 需 HBuilderX 4.61+)
  • App-iOS:编译为 Swift
  • 底层仅依赖 uni.* 原生导航 API(navigateTo / redirectTo / reLaunch / navigateBack / switchTab)
  • 导航动画字段官方仅 App 支持(Android 4.18+ / iOS 4.25+ / HarmonyOS 4.61+),小程序端官方不支持;H5 端由 AnimationPlugin 以 WAAPI 实现
  • 物理返回键 / TabBar 切换不经过路由器,通过 syncRoute() 在 onShow 自动对齐

License

MIT

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

许可协议

MIT协议