# 应用路由事件概述

应用路由事件用于从应用级别监听主页面路由的开始和完成,也可以在路由真正执行前重写目标页面。

它适合处理路由上报、全局状态重置、访问控制、无效入口页纠正和页面迁移等与“一次路由”相关的逻辑。如果逻辑只与单个页面的创建、显示或销毁有关,应优先使用对应的页面生命周期

应用路由事件只作用于主页面路由。dialogPage 的打开、关闭以及随所属页面销毁,均不会触发本页 API。

# API 列表

API 说明
uni.onBeforeAppRoute 监听路由执行前的事件
uni.offBeforeAppRoute 取消监听路由执行前的事件
uni.onAppRoute 监听路由成功后的事件
uni.offAppRoute 取消监听路由成功后的事件
uni.rewriteRoute 在路由执行前重写本次路由

# 事件时序

一次成功路由的主要执行顺序如下:

发起路由
  -> 解析路径并校验目标
  -> onBeforeAppRoute
  -> 执行路由逻辑
  -> 目标页面 onShow
  -> onAppRoute
  -> 路由转场动画完成

新页面创建时,相关事件和页面生命周期的顺序为:

onBeforeAppRoute -> onLoad -> onShow -> onAppRoute

返回已有页面或切换到已存在的 tabBar 页面时,不会再次触发 onLoad,顺序为:

onBeforeAppRoute -> onShow -> onAppRoute

onBeforeAppRoute 在页面栈变化以及页面创建、销毁等实际副作用发生前触发。onAppRoute 在路由成功且目标页面的 onShow 执行后触发,不等待路由转场动画完成。

# 触发场景

场景 onBeforeAppRoute onAppRoute 可重写
应用启动并进入有效首页或二级页面 触发 路由成功后触发
应用直接启动到不存在的页面 触发,notFoundtrue;支付宝小程序固定为 false 未重写时按缺页流程触发;支付宝小程序不触发 支持 rewriteRoute 的平台可重写
navigateToredirectToreLaunch 成功 触发 路由成功后触发
切换到其他 tabBar 页面 触发 路由成功后触发 是,且目标必须是 tabBar 页面
switchTab 到当前 tabBar 页面 不触发 不触发
navigateBack、系统返回、返回手势或 Web History 后退 触发 路由成功后触发
路由 API 参数错误或目标页面校验失败 不触发;支付宝小程序仍会触发,且 notFoundfalse 不触发
onBeforeAppRoute 已触发,但路由随后取消或执行失败 已触发 不触发 仅可在同步回调阶段重写
应用从后台恢复,但主页面路由未变化 不触发 不触发
dialogPage 打开、关闭或随所属页面销毁 不触发 不触发

监听器注册前已经发生的事件不会补发。如需监听或重写 appLaunch,应在 onLaunch 生命周期中或之前尽早注册监听器。

# 事件参数

onBeforeAppRouteonAppRoute 的公共事件参数含义如下:

属性 说明
path 目标页面路径,不包含开头的 /
query 当前轮路由解析得到的页面参数
openType 路由类型。发生重写时保持原路由类型不变
notFound 当前目标页面是否不存在
routeEventId 应用实例内唯一的路由事件标识

onAppRoute 还会提供 timeStamp,表示当前轮路由事件生成时的时间戳。

不同平台可能提供额外的事件字段。编写跨平台代码时,应只依赖本节列出的公共字段。

未发生重写时,同一次路由的 onBeforeAppRouteonAppRoute 使用相同的 routeEventId。每次成功重写都会生成新的路由事件和新的 routeEventId,最终的 onAppRoute 使用最后一轮 onBeforeAppRouterouteEventId

正常调用路由 API 时,参数错误或目标页面不存在会直接失败。除支付宝小程序外,此类失败不会产生应用路由事件。notFound 主要用于应用直接启动到不存在页面等已经进入路由流程的场景。

# 路由类型

openType 路由来源
appLaunch 应用首次启动;Web 直接访问首页或二级页面等入口路由
navigateTo uni.navigateTo;Web History 前进;无法识别为其他类型的新增页面路由
navigateBack uni.navigateBack;系统返回、返回手势;Web History 后退;小程序系统返回
redirectTo uni.redirectTo
reLaunch uni.reLaunch
switchTab uni.switchTab;用户切换到其他 tabBar 页面

平台差异

  • 微信小程序的路由事件监听要求基础库 3.5.5 及以上版本;rewriteRoute 要求基础库 3.8.0 及以上版本,并受微信客户端版本、运行平台和分包限制。微信开发者工具模拟器不支持 rewriteRoute,应在支持该能力的真机环境中验证。
  • 支付宝小程序通过 my.createRouteObserver 实现路由事件监听,并将支付宝的 backtabClick 分别归一化为 navigateBackswitchTab。支付宝的前置事件不提供目标页面是否存在的信息,因此 onBeforeAppRoutenotFound 固定为 false。当路由 API 的目标页面不存在时,支付宝仍会触发 onBeforeAppRoute,但不会触发 onAppRoute;应用直接启动到不存在的页面时同样不会触发 onAppRoute。支付宝小程序暂不支持 rewriteRoute

# uni.onAppRoute(callback)

监听应用路由成功后的事件。

# onAppRoute 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
5.25 5.25 5.25 5.25 5.25 5.25

# 参数

名称 类型 必填 兼容性 描述
callback (event: AppRouteEvent) => void
应用路由事件回调

# AppRouteEvent 的属性值

名称 类型 必备 兼容性 描述
path string
路由页面路径,不包含开头的斜杠
query UTSJSONObject
路由页面参数
openType string
应用路由类型。
合法值
appLaunch
navigateTo
navigateBack
redirectTo
reLaunch
switchTab
notFound boolean
路由页面是否不存在。支付宝小程序不提供该信息,固定为 false
timeStamp number
事件触发时的时间戳
routeEventId string
路由事件唯一标识
page IAnyObject
当前打开页面的相关配置
pipMode string
可选值:
- 'min': 视频页面缩小为小窗;
- 'max': 视频小窗还原为页面;
合法值
min
max
renderer string
渲染引擎

可选值:
- 'webview': Webview 渲染引擎;
- 'skyline': Skyline 渲染引擎;
- 'xr-frame': xr-frame 解决方案;
合法值
webview
skyline
xr-frame
webviewId number
当前页面 id

# 参见

# 使用说明

onAppRoute 只描述最终实际生效的路由。一次路由发生重写时,被替换的中间目标不会触发 onAppRoute,只有最终成功进入的页面触发一次。

监听器抛出的异常不会中断底层路由流程,但应在监听器内部妥善处理业务异常。

const appRouteCallback = (event : AppRouteEvent) => {
  console.log(`路由完成:${event.openType} ${event.path}`)
  console.log(`路由参数:${JSON.stringify(event.query)}`)
}

uni.onAppRoute(appRouteCallback)

// 不再监听时,传入注册时的同一个函数对象。
uni.offAppRoute(appRouteCallback)

# uni.offAppRoute(callback?)

取消监听应用路由事件。不传 callback 时移除全部监听器。

# offAppRoute 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
5.25 5.25 5.25 5.25 5.25 5.25

# 参数

名称 类型 必填 兼容性
callback (event: AppRouteEvent) => void

# AppRouteEvent 的属性值

名称 类型 必备 兼容性 描述
path string
路由页面路径,不包含开头的斜杠
query UTSJSONObject
路由页面参数
openType string
应用路由类型。
合法值
appLaunch
navigateTo
navigateBack
redirectTo
reLaunch
switchTab
notFound boolean
路由页面是否不存在。支付宝小程序不提供该信息,固定为 false
timeStamp number
事件触发时的时间戳
routeEventId string
路由事件唯一标识
page IAnyObject
当前打开页面的相关配置
pipMode string
可选值:
- 'min': 视频页面缩小为小窗;
- 'max': 视频小窗还原为页面;
合法值
min
max
renderer string
渲染引擎

可选值:
- 'webview': Webview 渲染引擎;
- 'skyline': Skyline 渲染引擎;
- 'xr-frame': xr-frame 解决方案;
合法值
webview
skyline
xr-frame
webviewId number
当前页面 id

# 参见

# 移除监听器

传入监听函数时,只移除同一个函数对象对应的监听器;不传参数或传入 null 时,移除通过 onAppRoute 注册的全部监听器。

const callback1 = (event : AppRouteEvent) => {
  console.log(event.path)
}
const callback2 = (event : AppRouteEvent) => {
  console.log(event.openType)
}

uni.onAppRoute(callback1)
uni.onAppRoute(callback2)

// 只移除 callback1。
uni.offAppRoute(callback1)

// 移除全部 onAppRoute 监听器。
uni.offAppRoute()

onAppRouteonBeforeAppRoute 的监听器相互独立,清空其中一类不会影响另一类。

# uni.onBeforeAppRoute(callback)

监听应用路由发生前的事件。

# onBeforeAppRoute 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
5.25 5.25 5.25 5.25 5.25 5.25

# 参数

名称 类型 必填 兼容性 描述
callback (event: BeforeAppRouteEvent) => void
应用路由前置事件回调

# BeforeAppRouteEvent 的属性值

名称 类型 必备 兼容性 描述
path string
路由页面路径,不包含开头的斜杠
query UTSJSONObject
路由页面参数
openType string
应用路由类型。
合法值
appLaunch
navigateTo
navigateBack
redirectTo
reLaunch
switchTab
notFound boolean
路由页面是否不存在。支付宝小程序不提供该信息,固定为 false
routeEventId string
路由事件唯一标识
page IAnyObject
当前打开页面的相关配置
pipMode string
可选值:
- 'min': 视频页面缩小为小窗;
- 'max': 视频小窗还原为页面;
合法值
min
max
renderer string
渲染引擎

可选值:
- 'webview': Webview 渲染引擎;
- 'skyline': Skyline 渲染引擎;
- 'xr-frame': xr-frame 解决方案;
合法值
webview
skyline
xr-frame
webviewId number
当前页面 id

# 参见

# 使用说明

onBeforeAppRoute 回调同步执行。可以根据目标页面、路由参数和路由类型记录信息,也可以在该回调中同步调用 rewriteRoute

const beforeAppRouteCallback = (event : BeforeAppRouteEvent) => {
  console.log(`准备路由:${event.openType} ${event.path}`)
  console.log(`路由参数:${JSON.stringify(event.query)}`)
}

// 如需处理 appLaunch,应在 App.uvue 的 onLaunch 中尽早注册。
onLaunch(() => {
  uni.onBeforeAppRoute(beforeAppRouteCallback)
})

同一个 routeEventId 对应的 onBeforeAppRoute 最多触发一次。重写后的目标会作为新一轮路由再次触发 onBeforeAppRoute,并使用新的 routeEventId

# uni.offBeforeAppRoute(callback?)

取消监听应用路由前置事件。不传 callback 时移除全部监听器。

# offBeforeAppRoute 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
5.25 5.25 5.25 5.25 5.25 5.25

# 参数

名称 类型 必填 兼容性
callback (event: BeforeAppRouteEvent) => void

# BeforeAppRouteEvent 的属性值

名称 类型 必备 兼容性 描述
path string
路由页面路径,不包含开头的斜杠
query UTSJSONObject
路由页面参数
openType string
应用路由类型。
合法值
appLaunch
navigateTo
navigateBack
redirectTo
reLaunch
switchTab
notFound boolean
路由页面是否不存在。支付宝小程序不提供该信息,固定为 false
routeEventId string
路由事件唯一标识
page IAnyObject
当前打开页面的相关配置
pipMode string
可选值:
- 'min': 视频页面缩小为小窗;
- 'max': 视频小窗还原为页面;
合法值
min
max
renderer string
渲染引擎

可选值:
- 'webview': Webview 渲染引擎;
- 'skyline': Skyline 渲染引擎;
- 'xr-frame': xr-frame 解决方案;
合法值
webview
skyline
xr-frame
webviewId number
当前页面 id

# 参见

# 移除监听器

offBeforeAppRoute 的移除规则与 offAppRoute 相同:传入注册时的同一个函数对象,只移除该监听器;不传参数或传入 null,移除全部前置路由监听器。

const beforeAppRouteCallback = (event : BeforeAppRouteEvent) => {
  console.log(event.path)
}

uni.onBeforeAppRoute(beforeAppRouteCallback)
uni.offBeforeAppRoute(beforeAppRouteCallback)

// 移除全部 onBeforeAppRoute 监听器。
uni.offBeforeAppRoute()

# uni.rewriteRoute(options)

在应用路由前置事件回调中重写当前路由。

# rewriteRoute 兼容性 ?

Web 微信小程序 支付宝小程序 Android iOS HarmonyOS
5.25 5.25 x 5.25 5.25 5.25

# 参数

名称 类型 必填 兼容性
options RewriteRouteOptions
名称 类型 必备 兼容性 描述
url string (string.PageURIString)
重写后的页面路径
preserveQuery boolean
是否保留原路由参数,默认 false
success (result: RewriteRouteSuccess) => void
接口调用成功的回调函数
fail (result: RewriteRouteFail) => void
接口调用失败的回调函数
complete (result: RewriteRouteComplete) => void
接口调用结束的回调函数

# RewriteRouteSuccess 的属性值

名称 类型 必备 兼容性
errMsg string

# RewriteRouteFail 的属性值

名称 类型 必备 兼容性 描述
errCode number
路由错误码
- 4: 框架内部异常
errSubject string
统一错误主题(模块)名称
data any
错误信息中包含的数据
cause Error 源错误信息,可以包含多个错误,详见SourceError
errMsg string

# RewriteRouteComplete 的属性值

名称 类型 必备 兼容性
errMsg string

# 参见

# 路由重写规则

rewriteRoute 用于重写当前正在处理的路由事件,且不支持 Promise 风格调用。调用时需遵守以下规则:

  • 只能在 onBeforeAppRoute 回调中同步调用。在回调外调用,或在回调中的异步任务内调用,都会失败。
  • 同一个 routeEventId 只允许成功重写一次。存在多个前置监听器时,首次重写成功后,同一轮的后续重写调用会失败。
  • 重写只改变目标路径和参数,不改变原路由的 openType
  • navigateBack 路由不允许重写。
  • 重写后的目标必须符合原路由类型的约束。例如,switchTab 只能重写到 tabBar 页面,navigateTo 不能重写到 tabBar 页面。
  • 重写目标会重新执行路径、页面存在性和路由类型校验。校验失败时保留当前轮的原目标,并通过 fail 返回失败信息。
  • 框架会限制连续重写次数以避免循环重写,超过限制时本次重写失败。微信小程序直接使用宿主的重写能力,遵循微信小程序的限制。

preserveQuery 默认为 false

  • false 时,使用 url 中携带的参数。
  • true 时,完整保留当前路由事件的参数,并丢弃 url 中携带的参数。

例如,当前目标参数为 a=1,重写地址为 /pages/new/new?b=2preserveQueryfalse 时最终参数为 b=2;为 true 时最终参数为 a=1

const beforeAppRouteCallback = (event : BeforeAppRouteEvent) => {
  if (
    event.openType == 'navigateTo' &&
    event.path == 'pages/old/old'
  ) {
    uni.rewriteRoute({
      url: '/pages/new/new?from=rewrite',
      preserveQuery: false,
      success: (result) => {
        console.log(result.errMsg)
      },
      fail: (error) => {
        console.error(error.errMsg)
      },
      complete: (result) => {
        console.log(result.errMsg)
      }
    })
  }
}

uni.onBeforeAppRoute(beforeAppRouteCallback)

success 表示本次重写请求已被接受;fail 表示本次重写被拒绝;无论成功或失败都会调用 complete

# 连续重写

重写后的目标会作为新的路由事件重新触发 onBeforeAppRoute。因此,“同一个路由事件只允许成功重写一次”不表示一次用户跳转只能重写一次。

A -> onBeforeAppRoute(routeEventId=1) -> 重写到 B
B -> onBeforeAppRoute(routeEventId=2) -> 重写到 C
C -> onBeforeAppRoute(routeEventId=3) -> 执行路由
C -> onAppRoute(routeEventId=3)

业务代码应避免不同重写规则之间形成循环。

完整示例代码参考 hello uni-app x 应用路由事件示例

# 通用类型

# GeneralCallbackResult

名称 类型 必备 兼容性 描述
errMsg string
错误信息