uni-app 路由跳转与页面导航 —— 终极详解(对标 iOS / Android / 鸿蒙三端原生)

19 阅读12分钟

参考官方文档:


一、核心概念:uni-app 的路由到底是什么?

1.1 一句话定义

uni-app 的路由(Route) = 框架统一管理的页面注册表 + 页面栈 + 跳转规则

不是 Vue Router。uni-app 没有使用 vue-router,而是自己实现了一套类小程序的路由系统。原因是:小程序平台(微信、支付宝等)本身就有自己的页面栈管理机制,uni-app 必须兼容所有平台,所以用 pages.json 做统一注册,用框架内置的页面栈做统一管理。

1.2 与 Vue Router 的本质区别

对比项Vue Router(Web SPA)uni-app 路由
路由配置文件router/index.js 中用代码配置pages.json 中用 JSON 配置
页面切换方式同一个 HTML 文件内切换组件(SPA)真正切换页面(每个页面是独立的 WebView / 原生页面)
页面栈管理浏览器 History 或 Hash框架自维护的页面栈(最多 10 层)
路由守卫beforeEach / beforeEnter / beforeResolve无内置守卫,需用 uni.addInterceptor 自行拦截
动态路由支持 :id* 通配符不支持动态路由,所有页面必须静态注册
嵌套路由支持 <router-view> 嵌套不支持页面嵌套页面

二、路由注册:pages.json(一切的起点)

2.1 官方文档原文核心

uni-app 页面路由为框架统一管理,开发者需要在 pages.json 里配置每个路由页面的路径和页面样式。类似小程序在 app.json 中配置页面路由。

2.2 完整配置示例

{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页",
        "navigationBarBackgroundColor": "#007AFF",
        "enablePullDownRefresh": true
      }
    },
    {
      "path": "pages/detail/detail",
      "style": {
        "navigationBarTitleText": "详情"
      }
    },
    {
      "path": "pages/mine/mine",
      "style": {
        "navigationBarTitleText": "我的"
      }
    }
  ],
  "tabBar": {
    "list": [
      { "pagePath": "pages/index/index", "text": "首页", "iconPath": "static/tab-home.png", "selectedIconPath": "static/tab-home-active.png" },
      { "pagePath": "pages/mine/mine", "text": "我的", "iconPath": "static/tab-mine.png", "selectedIconPath": "static/tab-mine-active.png" }
    ]
  },
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  }
}

2.3 关键规则

规则说明
pages 数组第一项 = 应用首页框架启动时自动加载第一个页面
path 不带文件后缀pages/index/index,不写 .vue
所有可跳转页面必须注册未注册的页面跳转无效,控制台报错
tabBar 页面必须同时出现在 pages 数组中否则 tabBar 不生效
tabBar 最少 2 项,最多 5 项平台限制

2.4 对标三端原生

uni-appiOSAndroid鸿蒙 ArkTS
pages.json 注册页面Storyboard 中拖入 ViewController 并设 Storyboard ID;或代码中 UIViewController 子类AndroidManifest.xml 中注册 <activity android:name=".DetailActivity">src/main/resources/base/profile/main_pages.jsonsrc 数组中注册页面路径
pages[0] = 首页window.rootViewController = 根控制器LAUNCHER intent-filter 的 Activitymain_pages.json 中第一个路径
tabBar.listUITabBarController + 各 tab 的 UIViewControllerBottomNavigationView / TabLayout + FragmentTabs 组件 + TabContent

三、页面栈模型(最核心的概念)

3.1 官方文档原文

框架以的形式管理当前所有页面,当发生路由切换的时候,页面栈的表现如下:

3.2 页面栈变化表(官方)

路由方式页面栈表现触发时机
初始化新页面入栈uni-app 打开的第一个页面
打开新页面新页面入栈调用 uni.navigateTo 或使用 <navigator open-type="navigate">
页面重定向当前页面出栈,新页面入栈调用 uni.redirectTo 或使用 <navigator open-type="redirect">
页面返回页面不断出栈,直到目标返回页调用 uni.navigateBack 或使用 <navigator open-type="navigateBack">
Tab 切换当前页面出栈,新 Tab 页面入栈(非 tabBar 页面全部出栈)调用 uni.switchTab 或使用 <navigator open-type="switchTab">
重启动所有页面出栈,新页面入栈调用 uni.reLaunch 或使用 <navigator open-type="reLaunch">

3.3 图示理解

【初始状态】打开 App,加载首页
┌──────────┐
│ 首页(A)  │  ← 栈底 = 栈顶(只有1个页面)
└──────────┘

【navigateTo → 详情页(B)】
┌──────────┐
│ 详情页(B)│  ← 栈顶(当前显示)
│ 首页(A)  │  ← 栈底
└──────────┘

【再 navigateTo → 评论页(C)】
┌──────────┐
│ 评论页(C)│  ← 栈顶
│ 详情页(B)│
│ 首页(A)  │  ← 栈底
└──────────┘

【navigateBack delta=1】→ 回到 B
┌──────────┐
│ 详情页(B)│  ← 栈顶
│ 首页(A)  │  ← 栈底
└──────────┘

【redirectTo → 结果页(D)】→ B 出栈,D 入栈
┌──────────┐
│ 结果页(D)│  ← 栈顶(当前显示)
│ 首页(A)  │  ← 栈底(B 被销毁了!)
└──────────┘

【reLaunch → 登录页(E)】→ 全部清空
┌──────────┐
│ 登录页(E)│  ← 唯一的页面
└──────────┘

【switchTab → 我的页】→ 关闭所有非 Tab 页
┌──────────┐
│ 我的页   │  ← 栈顶(tabBar 页面)
└──────────┘

3.4 页面栈上限

页面栈最多 10 层。 超过后 uni.navigateTo 将失效(静默失败,不跳转也不报错)。

3.5 对标三端原生

uni-app 页面栈iOSAndroid鸿蒙
栈最多 10 层UINavigationController.viewControllers 数组,理论无上限(受内存限制)Task Stack(任务栈),默认无硬性上限(但系统可能回收)router 路由栈,官方建议不超过 32 层
getCurrentPages() 获取栈navigationController.viewControllersActivityManager.getRunningTasks() 或自行维护栈router.getState() 获取当前路由信息
栈底 = 首页viewControllers[0] = rootViewController任务栈底部 = Launcher Activity路由栈第一个元素

四、两种跳转方式:声明式 vs 编程式

4.1 官方文档原文

uni-app 有两种页面路由跳转方式:

  1. 使用 navigator 组件(声明式)
  2. 调用 API(编程式)

4.2 方式一:<navigator> 组件(声明式)

类似 HTML 的 <a> 标签,但只能跳转本地页面

<!-- 最基础用法 -->
<navigator url="/pages/detail/detail?id=123">去详情</navigator>

<!-- 指定跳转类型 -->
<navigator url="/pages/mine/mine" open-type="switchTab">去我的</navigator>

<!-- 返回上一页 -->
<navigator open-type="navigateBack" delta="1">返回</navigator>

<navigator> 完整属性表(官方)

属性名类型默认值说明
urlString应用内的跳转链接,相对路径或绝对路径,不加 .vue 后缀
open-typeStringnavigate跳转类型(见下表)
deltaNumber1open-type="navigateBack" 时,返回的层数
animation-typeString平台默认跳转动画类型(仅 App 端有效)
animation-durationNumber平台默认动画时长(ms)
hover-classStringnavigator-hover点击态样式类
hover-start-timeNumber50按住后多久出现点击态(ms)
hover-stay-timeNumber600手指松开后点击态保留时间(ms)

open-type 有效值

open-type 值等价的 API说明
navigateuni.navigateTo()保留当前页,跳转新页面(默认值
redirectuni.redirectTo()关闭当前页,跳转新页面
switchTabuni.switchTab()跳转到 tabBar 页面,关闭所有非 tabBar 页面
reLaunchuni.reLaunch()关闭所有页面,打开新页面
navigateBackuni.navigateBack()关闭当前页面,返回上一级或多级页面
exit退出小程序(仅微信小程序 2.1.0+)

对标三端原生

uni-app <navigator>iOSAndroid鸿蒙
声明式跳转组件Storyboard 中的 Segue(拖线连接两个 VC)XML 中的 <intent-filter> + startActivity;或 Jetpack Navigation 的 <action>Navigation 组件的 navDestination + router.pushUrl
open-type 切换行为Segue 类型:push / present / replaceIntent 的 Flag:FLAG_ACTIVITY_NEW_TASK / CLEAR_TASKrouter.pushUrl / replaceUrl / back

4.3 方式二:API 编程式跳转(重点)


五、5 个路由 API 逐一详解

5.1 uni.navigateTo(OBJECT) — 压栈跳转(最常用)

官方定义

保留当前页面,跳转到应用内的某个页面。使用 uni.navigateBack 可以返回到原页面。

参数表

参数类型必填说明
urlString需要跳转的应用内非 tabBar 页面路径,路径后可带参数,参数与路径用 ? 分隔,多个参数用 & 连接
eventsObject页面间通信通道(2.8.9+ 支持)
animationTypeString窗口动画类型(仅 App 端)
animationDurationNumber窗口动画时长(ms,仅 App 端)
successFunction接口调用成功的回调
failFunction接口调用失败的回调
completeFunction接口调用结束的回调(成功或失败都执行)

代码示例

// 基础跳转
uni.navigateTo({
  url: '/pages/detail/detail?id=123&name=test'
})

// 带 EventChannel 的跳转(页面间通信)
uni.navigateTo({
  url: '/pages/detail/detail',
  events: {
    // 为被打开页面注册的监听事件
    'onDataChanged': function(data) {
      console.log('子页面传回的数据:', data)
    }
  },
  success: function(res) {
    // 通过 eventChannel 向被打开页面传送数据
    res.eventChannel.emit('initData', { id: 123, title: 'Hello' })
  }
})

⚠️ 限制

  • 不能跳转到 tabBar 页面(会静默失败)
  • 页面栈最多 10 层,超出后此 API 无效

对标三端

iOSAndroid鸿蒙
代码self.navigationController?.pushViewController(detailVC, animated: true)startActivity(Intent(this, DetailActivity::class.java))router.pushUrl({ url: 'pages/detail' })
传参detailVC.itemId = 123(直接属性赋值)intent.putExtra("id", 123)router.pushUrl({ url: '...', params: { id: 123 } })
动画push 默认从右向左滑入默认从右向左(可自定义 overridePendingTransition默认转场动画
栈行为新 VC 压入 viewControllers 数组末尾新 Activity 压入 Task Stack 顶部新页面压入路由栈顶部

5.2 uni.redirectTo(OBJECT) — 替换跳转

官方定义

关闭当前页面,跳转到应用内的某个页面。

参数表

参数类型必填说明
urlString需要跳转的应用内非 tabBar 页面路径
animationTypeString窗口动画类型(仅 App 端)
animationDurationNumber窗口动画时长(仅 App 端)
success/fail/completeFunction回调

代码示例

// 登录成功后跳转到首页,关闭登录页(用户不能返回登录页)
uni.redirectTo({
  url: '/pages/home/home'
})

⚠️ 限制

  • 不能跳转到 tabBar 页面
  • 当前页面会被销毁(触发 onUnload),无法返回

与 navigateTo 的核心区别

navigateToredirectTo
当前页保留在栈中销毁(出栈)
能否返回能(navigateBack)不能
页面栈变化+1±0(一出一进)
典型场景列表→详情中间过渡页→结果页

对标三端

iOSAndroid鸿蒙
代码navigationController.setViewControllers([newVC], animated: true) 或先 pop 再 pushstartActivity(intent); finish();router.replaceUrl({ url: 'pages/home' })
本质替换栈顶 VC新 Activity 入栈 + 旧 Activity 销毁替换路由栈顶元素
生命周期旧 VC 触发 viewDidDisappear + dealloc旧 Activity 触发 onPause → onStop → onDestroy旧页面触发 onPageHide → aboutToDisappear

5.3 uni.reLaunch(OBJECT) — 清栈重启

官方定义

关闭所有页面,打开到应用内的某个页面。

代码示例

// 退出登录,回到登录页,清空所有页面栈
uni.reLaunch({
  url: '/pages/login/login'
})

⚠️ 特点

  • 所有页面全部销毁(包括 tabBar 页面)
  • 页面栈清零,只剩新打开的这一个页面
  • 可以跳转到 tabBar 页面,也可以跳转到非 tabBar 页面

对标三端

iOSAndroid鸿蒙
代码window.rootViewController = UINavigationController(rootViewController: loginVC)`Intent intent = new Intent(this, LoginActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASKIntent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);`router.clear(); router.replaceUrl({ url: 'pages/login' })
本质直接换掉根控制器,旧栈全部释放清空整个任务栈,创建新任务清空路由栈,替换为新页面
内存影响所有旧 VC 被释放所有旧 Activity 被 destroy所有旧页面组件被销毁

5.4 uni.switchTab(OBJECT) — Tab 页切换

官方定义

跳转到 tabBar 页面,并关闭所有其他非 tabBar 页面。

代码示例

uni.switchTab({
  url: '/pages/mine/mine'
})

⚠️ 关键限制

限制说明
只能跳 tabBar 页面url 必须是 tabBar.list 中声明的页面
不能传参数url 后面拼参数无效!
关闭所有非 tabBar 页面页面栈中非 Tab 页面全部销毁

如果需要给 Tab 页传数据怎么办?

// 方案1:全局状态管理(Pinia / Vuex)
import { useStore } from '@/store'
const store = useStore()
store.selectedId = 123
uni.switchTab({ url: '/pages/mine/mine' })

// 方案2:uni.$emit 事件总线
uni.$emit('updateMineData', { id: 123 })
uni.switchTab({ url: '/pages/mine/mine' })

// 方案3:uni.setStorageSync 本地缓存
uni.setStorageSync('pendingData', { id: 123 })
uni.switchTab({ url: '/pages/mine/mine' })

对标三端

iOSAndroid鸿蒙
代码tabBarController.selectedIndex = 2tabBarController.selectedViewController = mineVCbottomNavigationView.selectedItemId = R.id.mine 或切换 Fragment修改 Tabs 组件的 index 状态变量
本质UITabBarController 切换当前显示的子控制器切换 BottomNavigationView 选中项 + FragmentTransaction show/hide切换 TabContent 显示
其他 Tab 页不销毁,只是被隐藏(viewDidDisappear不销毁,Fragment 被 hide 或 detach不销毁,只是不显示

5.5 uni.navigateBack(OBJECT) — 返回

官方定义

关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层。

参数表

参数类型默认值说明
deltaNumber1返回的页面数,如果 delta 大于现有页面数,则返回到首页

代码示例

// 返回上一页
uni.navigateBack({ delta: 1 })

// 返回上3页
uni.navigateBack({ delta: 3 })

// 动态计算:返回到首页
const pages = getCurrentPages()
uni.navigateBack({ delta: pages.length - 1 })

对标三端

iOSAndroid鸿蒙
返回1层navigationController.popViewController(animated: true)finish() 或用户按返回键router.back()
返回多层navigationController.popToViewController(targetVC, animated: true)连续 finish() 多次;或用 Intent.FLAG_ACTIVITY_CLEAR_TOProuter.back() 多次调用
返回首页navigationController.popToRootViewController(animated: true)Intent + `FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_SINGLE_TOP`循环 router.back() 直到栈底

六、5 个 API 终极对比表

API当前页处理页面栈变化能跳 tabBar?能传参数?典型场景
navigateTo保留叠加(+1)❌ 不能✅ URL 参数 / EventChannel列表→详情
redirectTo关闭替换(±0)❌ 不能✅ URL 参数中间页→结果页
reLaunch全部关闭清零→新建(=1)✅ 能✅ URL 参数退出登录→登录页
switchTab关闭非Tab页仅保留Tab页✅ 只能跳Tab❌ 不能传参切换底部Tab
navigateBack关闭当前页减少(-delta)返回上一页

七、页面传参详解

7.1 URL 参数(最基础)

// 发送方
uni.navigateTo({
  url: '/pages/detail/detail?id=123&title=' + encodeURIComponent('你好世界')
})

// 接收方(目标页面的 onLoad 中)
onLoad(options) {
  console.log(options.id)      // '123'
  console.log(decodeURIComponent(options.title))  // '你好世界'
}

对标三端

iOSAndroid鸿蒙
传参方式直接属性赋值:detailVC.itemId = 123intent.putExtra("id", 123)router.pushUrl({ params: { id: 123 } })
取参方式在目标 VC 中直接读属性getIntent().getIntExtra("id", 0)router.getParams()['id']

7.2 EventChannel 页面通信(2.8.9+,推荐)

这是 uni-app 独有的机制,不需要全局状态,直接在两个页面之间建立通信管道。

// ===== 页面A(发送方)=====
uni.navigateTo({
  url: '/pages/pageB/pageB',
  events: {
    // 监听页面B发来的事件
    'onResult': function(data) {
      console.log('B 传回的数据:', data)
    }
  },
  success: function(res) {
    // 向页面B发送数据
    res.eventChannel.emit('initData', { id: 123, list: [1,2,3] })
  }
})

// ===== 页面B(接收方)=====
onLoad() {
  const eventChannel = this.getOpenerEventChannel()
  
  // 监听页面A发来的数据
  eventChannel.on('initData', function(data) {
    console.log('A 发来的数据:', data)
  })
  
  // 向页面A发送数据
  eventChannel.emit('onResult', { status: 'success' })
}

对标三端

iOSAndroid鸿蒙
类似机制闭包回调 / delegate 协议 / NotificationCenterstartActivityForResult + onActivityResult(旧)/ ActivityResultLauncher(新)routerback 配合 params 回传;或 EventHub
本质双向通信管道请求-响应模式事件订阅

7.3 全局事件总线 uni.$emit / uni.$on

// 任意页面发送
uni.$emit('dataUpdated', { id: 456 })

// 任意页面监听(通常在 onLoad 中注册,onUnload 中注销)
onLoad() {
  uni.$on('dataUpdated', this.onDataUpdated)
},
onUnload() {
  uni.$off('dataUpdated', this.onDataUpdated)
},
methods: {
  onDataUpdated(data) {
    console.log('收到更新:', data)
  }
}

八、页面生命周期与路由跳转的关系

8.1 页面生命周期一览(官方)

生命周期触发时机触发次数
onLoad(options)页面加载时,可获取 URL 参数一次
onShow()页面显示/切入前台时多次(每次显示都触发)
onReady()页面初次渲染完成一次
onHide()页面隐藏/切入后台时多次
onUnload()页面卸载(销毁)时一次

8.2 不同跳转方式触发的生命周期

跳转方式旧页面触发新页面触发
navigateToonHideonLoad → onShow → onReady
navigateBackonUnload(被销毁的那个)前一个页面触发 onShow
redirectToonUnloadonLoad → onShow → onReady
reLaunch所有页面 onUnloadonLoad → onShow → onReady
switchTab非 Tab 页面 onUnload;当前 Tab 页 onHide目标 Tab 页 onShow(首次还有 onLoad → onReady

8.3 对标三端原生生命周期

uni-appiOS UIViewControllerAndroid Activity鸿蒙 ArkTS 页面
onLoadviewDidLoadonCreateaboutToAppear
onShowviewWillAppear / viewDidAppearonResumeonPageShow
onReadyviewDidLayoutSubviews(首次布局完成)onWindowFocusChanged(true)页面首次渲染完成回调
onHideviewWillDisappear / viewDidDisappearonPause / onStoponPageHide
onUnloaddealloc(ARC 释放时)onDestroyaboutToDisappear

九、getCurrentPages() — 获取当前页面栈

官方定义

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。

const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]  // 当前页面
const prevPage = pages[pages.length - 2]     // 上一个页面

console.log(currentPage.route)  // 当前页面路由路径,如 'pages/detail/detail'

每个页面实例的属性和方法

属性/方法说明平台
page.route当前页面的路由路径全平台
page.$vm当前页面的 Vue 实例全平台
page.$getAppWebview()获取当前页面的 webview 对象实例仅 App

⚠️ 注意

请勿修改页面栈,以免造成页面状态错误。


十、App 端特有的窗口动画(animationType

uni.navigateTouni.redirectToApp 端支持自定义窗口动画:

animationType 值说明
slide-in-right从右侧滑入(默认
slide-in-left从左侧滑入
slide-in-top从上侧滑入
slide-in-bottom从下侧滑入
fade-in淡入
zoom-out缩放淡入
pop-in从底部弹出
none无动画
uni.navigateTo({
  url: '/pages/detail/detail',
  animationType: 'slide-in-bottom',
  animationDuration: 300
})

对标三端

iOSAndroid鸿蒙
自定义转场动画UIViewControllerTransitioningDelegate + 自定义 UIViewControllerAnimatedTransitioningoverridePendingTransition(enterAnim, exitAnim)ActivityOptions.makeCustomAnimation()pageTransition 中自定义 PageTransitionEnter / PageTransitionExit

十一、路由守卫(uni-app 没有内置,需自行实现)

uni-app 没有 Vue Router 的 beforeEach 全局守卫。但可以用 uni.addInterceptor 拦截所有路由 API:

// 在 App.vue 的 onLaunch 或 main.js 中
const interceptors = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab']

interceptors.forEach(method => {
  uni.addInterceptor(method, {
    invoke(args) {
      // 跳转前拦截
      const needLogin = ['/pages/order/order', '/pages/mine/mine']
      const token = uni.getStorageSync('token')
      
      if (needLogin.some(p => args.url.startsWith(p)) && !token) {
        uni.showToast({ title: '请先登录', icon: 'none' })
        uni.navigateTo({ url: '/pages/login/login' })
        return false  // 返回 false 阻止本次跳转
      }
    }
  })
})

对标三端

iOSAndroid鸿蒙
路由守卫pushViewController 前手动判断;或自定义 Router 类startActivity 前判断;或用 ActivityResultContracts 拦截router.pushUrl 前判断
框架级方案无内置(通常自封装 Router)Jetpack Navigation 的 NavigationUI + NavigationGuard(非官方)无内置

十二、完整技术栈对照总表

功能维度uni-appiOS 原生Android 原生鸿蒙 ArkTS
路由注册pages.jsonStoryboard / 代码注册 VCAndroidManifest.xml 注册 Activitymain_pages.json
页面容器框架页面栈(WebView / nvue)UINavigationControllerTask Stack(Activity 栈)router 路由栈
压栈跳转uni.navigateTopushViewController:animated:startActivity(intent)router.pushUrl()
替换跳转uni.redirectTo替换 viewControllers 栈顶startActivity + finish()router.replaceUrl()
清栈重启uni.reLaunchrootViewControllerCLEAR_TASK + NEW_TASKrouter.clear() + replaceUrl()
Tab 切换uni.switchTabUITabBarController.selectedIndexBottomNavigationView / TabLayoutTabs 组件 index
返回uni.navigateBackpopViewController / popToRootViewControllerfinish() / onBackPressed()router.back()
获取栈getCurrentPages()navigationController.viewControllersActivityManager / 自维护router.getState()
声明式跳转<navigator> 组件Storyboard SegueJetpack Navigation <action>Navigation + navPathStack
传参URL 参数 / EventChannel属性赋值 / delegateIntent.putExtra / Bundlerouter.pushUrl({ params })
双向通信EventChanneldelegate / closure / NotificationCenterstartActivityForResult / ActivityResultLauncherEventHub / emitter
全局事件uni.$emit / uni.$onNotificationCenterLocalBroadcastManager / EventBuscommonEventManager / emitter
路由守卫uni.addInterceptor(自行封装)手动判断 / 自封装 Router手动判断 / 拦截器模式手动判断
转场动画animationType 参数(App 端)UIViewControllerTransitioningDelegateoverridePendingTransition / ActivityOptionspageTransition
页面生命周期onLoad/onShow/onReady/onHide/onUnloadviewDidLoad/viewWillAppear/viewDidAppear/viewWillDisappear/dealloconCreate/onResume/onPause/onStop/onDestroyaboutToAppear/onPageShow/onPageHide/aboutToDisappear
页面栈上限10 层无硬性限制(受内存)无硬性限制(受系统回收)建议 ≤ 32 层
Vue Router 兼容不兼容(可在插件市场找 vue-router 适配插件)

十三、常见踩坑与最佳实践

13.1 必须避免的坑

原因解决方案
navigateTo 跳 tabBar 页无反应API 设计限制改用 switchTab
switchTab 传参拿不到API 设计限制用 Pinia / uni.$emit / Storage
页面栈超 10 层后跳转失效栈满关键节点用 redirectTo 替换;或用 reLaunch 重置
onLoad 在 Tab 页只执行一次Tab 页不会重新创建需要每次刷新就写在 onShow
redirectTo 后无法返回当前页已被销毁这是设计意图,确认业务需要再使用
URL 参数含中文或特殊字符未编码使用 encodeURIComponent() 编码

13.2 最佳实践总结

选择跳转方式的决策树:

目标页面是 tabBar 页面?
├── 是 → uni.switchTab
└── 否 → 需要保留当前页面(能返回)?
    ├── 是 → 页面栈是否已满(≥10)?
    │   ├── 是 → uni.redirectTo(替换,防止溢出)
    │   └── 否 → uni.navigateTo(最常用)
    └── 否 → 是否需要关闭所有页面?
        ├── 是 → uni.reLaunch
        └── 否 → uni.redirectTo

十四、参考文档链接汇总

文档链接
页面与路由跳转uniapp.dcloud.net.cn/tutorial/pa…
路由 API(5 个方法)uniapp.dcloud.net.cn/api/router.…
navigator 组件uniapp.dcloud.net.cn/component/n…
pages.json 配置uniapp.dcloud.net.cn/collocation…
getCurrentPagesuniapp.dcloud.net.cn/api/window/…
页面生命周期uniapp.dcloud.net.cn/tutorial/pa…

以上就是基于 uni-app 官方文档的完整梳理,覆盖了路由注册、页面栈模型、5 个 API 的参数/行为/限制、navigator 组件、传参方式、EventChannel 通信、生命周期联动、路由守卫、窗口动画等全部技术点,并逐一对标了 iOS(UINavigationController / UITabBarController)、Android(Activity Task Stack / Intent)、鸿蒙(router / Navigation)三端原生实现。如果某个部分需要更深入的代码级展开,随时告诉我。