uniapp页面路由

uni-app 路由详解:从入门到精通

本文基于 uni-app 页面路由文档 整理,详细介绍了 uni-app 中的路由 API 使用方法和最佳实践。

目录

  • 概述
  • [路由 API 详解](#路由 API 详解 "#%E8%B7%AF%E7%94%B1-api-%E8%AF%A6%E8%A7%A3")
    • [uni.navigateTo - 保留当前页面跳转](#uni.navigateTo - 保留当前页面跳转 "#uninavigateto---%E4%BF%9D%E7%95%99%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC")
    • [uni.redirectTo - 关闭当前页面跳转](#uni.redirectTo - 关闭当前页面跳转 "#uniredirectto---%E5%85%B3%E9%97%AD%E5%BD%93%E5%89%8D%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC")
    • [uni.reLaunch - 关闭所有页面跳转](#uni.reLaunch - 关闭所有页面跳转 "#unirelaunch---%E5%85%B3%E9%97%AD%E6%89%80%E6%9C%89%E9%A1%B5%E9%9D%A2%E8%B7%B3%E8%BD%AC")
    • [uni.switchTab - 跳转到 tabBar 页面](#uni.switchTab - 跳转到 tabBar 页面 "#uniswitchtab---%E8%B7%B3%E8%BD%AC%E5%88%B0-tabbar-%E9%A1%B5%E9%9D%A2")
    • [uni.navigateBack - 返回上一页](#uni.navigateBack - 返回上一页 "#uninavigateback---%E8%BF%94%E5%9B%9E%E4%B8%8A%E4%B8%80%E9%A1%B5")
  • [页面间通信 - EventChannel](#页面间通信 - EventChannel "#%E9%A1%B5%E9%9D%A2%E9%97%B4%E9%80%9A%E4%BF%A1---eventchannel")
  • 窗口动画配置
  • 注意事项和最佳实践
  • 总结

概述

uni-app 提供了丰富的路由 API,用于实现页面之间的跳转和导航。根据不同的使用场景,可以选择不同的路由方法。理解这些 API 的区别和使用场景,对于开发高质量的 uni-app 应用至关重要。

路由 API 详解

uni.navigateTo - 保留当前页面跳转

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

适用场景

  • 需要返回的页面跳转
  • 详情页、表单页等需要保留历史记录的页面

参数说明

参数 类型 必填 说明
url String 需要跳转的应用内非 tabBar 的页面的路径,路径后可以带参数
animationType String 窗口显示的动画效果(仅 App 支持)
animationDuration Number 窗口动画持续时间,单位为 ms(仅 App 支持)
events Object 页面间通信接口,用于监听被打开页面发送到当前页面的数据(2.8.9+)
success Function 接口调用成功的回调函数
fail Function 接口调用失败的回调函数
complete Function 接口调用结束的回调函数

代码示例

javascript 复制代码
// 在起始页面跳转到 test.vue 页面并传递参数
uni.navigateTo({
  url: 'test?id=1&name=uniapp',
  success: (res) => {
    console.log('跳转成功', res)
  },
  fail: (err) => {
    console.log('跳转失败', err)
  }
})

// 在 test.vue 页面接收参数
export default {
  onLoad: function (option) {
    console.log(option.id)    // 输出: 1
    console.log(option.name)  // 输出: uniapp
  }
}

传递复杂参数

javascript 复制代码
// 传递对象参数(需要序列化)
const data = {
  id: 1,
  name: 'uniapp',
  list: [1, 2, 3]
}

uni.navigateTo({
  url: `test?data=${encodeURIComponent(JSON.stringify(data))}`
})

// 接收参数
onLoad((options) => {
  const data = JSON.parse(decodeURIComponent(options.data))
  console.log(data)
})

uni.redirectTo - 关闭当前页面跳转

功能说明:关闭当前页面,跳转到应用内的某个页面。

适用场景

  • 登录成功后跳转到首页
  • 不需要返回的页面跳转
  • 替换当前页面

参数说明 :与 uni.navigateTo 相同(除了不支持 events 参数)

代码示例

javascript 复制代码
// 登录成功后跳转到首页
uni.redirectTo({
  url: '/pages/index/index'
})

与 navigateTo 的区别

javascript 复制代码
// A 页面
uni.navigateTo({
  url: 'B?id=1'
})

// B 页面
uni.navigateTo({
  url: 'C?id=1'
})

// 在 C 页面内 navigateBack,将返回 B 页面
// 但如果 B 页面使用的是 redirectTo,则返回 A 页面

uni.reLaunch - 关闭所有页面跳转

功能说明:关闭所有页面,打开到应用内的某个页面。

适用场景

  • 退出登录后跳转到登录页
  • 需要清空页面栈的场景
  • 重新初始化应用状态

代码示例

javascript 复制代码
// 退出登录
const logout = () => {
  // 清除用户信息
  uni.removeStorageSync('token')
  
  // 关闭所有页面,跳转到登录页
  uni.reLaunch({
    url: '/pages/login/login'
  })
}

uni.switchTab - 跳转到 tabBar 页面

功能说明:跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。

适用场景

  • 切换到底部导航栏页面
  • 从非 tabBar 页面返回到 tabBar 页面

重要提示

  • 只能跳转到 pages.json 中配置的 tabBar 页面
  • 跳转的 url 必须是在 tabBar 中定义的路径

代码示例

javascript 复制代码
// 跳转到首页(tabBar 页面)
uni.switchTab({
  url: '/pages/index/index'
})

pages.json 配置示例

json 复制代码
{
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页"
      },
      {
        "pagePath": "pages/user/user",
        "text": "我的"
      }
    ]
  }
}

uni.navigateBack - 返回上一页

功能说明:关闭当前页面,返回上一页面或多级页面。

参数说明

参数 类型 必填 说明
delta Number 返回的页面数,如果 delta 大于现有页面数,则返回到首页。默认值为 1
animationType String 窗口关闭的动画效果(仅 App 支持)
animationDuration Number 窗口关闭动画的持续时间,单位为 ms(仅 App 支持)

代码示例

javascript 复制代码
// 返回上一页
uni.navigateBack()

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

// 带动画效果返回(仅 App)
uni.navigateBack({
  delta: 1,
  animationType: 'pop-out',
  animationDuration: 300
})

实际应用场景

javascript 复制代码
// A 页面 -> B 页面 -> C 页面
// 在 C 页面内 navigateBack,将返回 B 页面
uni.navigateBack({
  delta: 1
})

// 如果想直接返回 A 页面
uni.navigateBack({
  delta: 2
})

页面间通信 - EventChannel

2.8.9+ 支持,HarmonyOS Next 不支持

EventChannel 提供了页面间事件通信的能力,可以在页面跳转时建立通信通道。

EventChannel 方法

emit - 触发事件
javascript 复制代码
// 在目标页面触发事件
eventChannel.emit('eventName', { data: 'value' })
on - 持续监听事件
javascript 复制代码
// 在源页面监听事件
eventChannel.on('eventName', (data) => {
  console.log('接收到数据:', data)
})
once - 监听事件一次
javascript 复制代码
// 只监听一次,触发后失效
eventChannel.once('eventName', (data) => {
  console.log('接收到数据:', data)
})
off - 取消监听
javascript 复制代码
// 取消所有监听
eventChannel.off('eventName')

// 取消指定的监听函数
eventChannel.off('eventName', fn)

完整示例

javascript 复制代码
// 源页面 - 发送数据
uni.navigateTo({
  url: '/pages/detail/detail',
  events: {
    // 监听目标页面发送的事件
    acceptDataFromDetail: (data) => {
      console.log('从详情页接收到的数据:', data)
    }
  },
  success: (res) => {
    // 通过 eventChannel 向目标页面发送数据
    res.eventChannel.emit('acceptDataFromOpenerPage', {
      data: '来自源页面的数据'
    })
  }
})

// 目标页面 - 接收和发送数据
export default {
  onLoad(options, context) {
    // 接收源页面发送的数据
    context.eventChannel.on('acceptDataFromOpenerPage', (data) => {
      console.log('接收到源页面的数据:', data)
    })
    
    // 向源页面发送数据
    context.eventChannel.emit('acceptDataFromDetail', {
      data: '来自详情页的数据'
    })
  }
}

窗口动画配置

本功能仅 App 支持。小程序自身不支持自定义动画。

uni-app 支持在 API、组件、pages.json 中配置窗口动画,优先级为:API > 组件 > pages.json

API 配置

javascript 复制代码
// 跳转时配置动画
uni.navigateTo({
  url: '../test/test',
  animationType: 'pop-in',
  animationDuration: 200
})

// 返回时配置动画
uni.navigateBack({
  delta: 1,
  animationType: 'pop-out',
  animationDuration: 200
})

组件配置

html 复制代码
<navigator 
  animation-type="pop-in" 
  animation-duration="300" 
  url="../test/test">
  跳转
</navigator>

<navigator 
  animation-type="pop-out" 
  animation-duration="300" 
  open-type="navigateBack">
  返回
</navigator>

pages.json 配置

json 复制代码
{
  "style": {
    "app-plus": {
      "animationType": "fade-in",
      "animationDuration": 300
    }
  }
}

支持的动画类型

显示动画 关闭动画 说明
slide-in-right slide-out-right 新窗体从右侧进入
slide-in-left slide-out-left 新窗体从左侧进入
slide-in-top slide-out-top 新窗体从顶部进入
slide-in-bottom slide-out-bottom 新窗体从底部进入
pop-in pop-out 新窗体从左侧进入,且老窗体被挤压而出
fade-in fade-out 新窗体从透明到不透明逐渐显示
zoom-out zoom-in 新窗体从小到大缩放显示
zoom-fade-out zoom-fade-in 新窗体从小到大逐渐放大并且从透明到不透明逐渐显示
none none 无动画

注意事项和最佳实践

1. 路由限制

  • navigateToredirectTo 只能打开非 tabBar 页面
  • switchTab 只能打开 tabBar 页面
  • reLaunch 可以打开任意页面

2. 页面栈管理

javascript 复制代码
// 注意页面栈的层级
// A 页面
uni.navigateTo({
  url: 'B?id=1'
})

// B 页面
uni.navigateTo({
  url: 'C?id=1'
})

// 在 C 页面内 navigateBack,将返回 B 页面
// 如果 B 页面使用的是 redirectTo,则返回 A 页面

3. H5 端特殊处理

H5 端页面刷新之后页面栈会消失,此时 navigateBack 不能返回。如果需要返回,可以使用 history.back() 导航到浏览器的其他历史记录。

javascript 复制代码
// #ifdef H5
if (getCurrentPages().length === 1) {
  history.back()
} else {
  uni.navigateBack()
}
// #endif

4. 不能在首页 onReady 之前进行页面跳转

javascript 复制代码
export default {
  onReady() {
    // 正确的做法:在 onReady 之后跳转
    uni.navigateTo({
      url: '/pages/detail/detail'
    })
  }
}

5. 参数传递最佳实践

javascript 复制代码
// ✅ 推荐:简单参数使用 URL 参数
uni.navigateTo({
  url: `/pages/detail/detail?id=${id}&name=${name}`
})

// ✅ 推荐:复杂对象使用 JSON 序列化
const complexData = {
  user: { id: 1, name: 'test' },
  list: [1, 2, 3]
}
uni.navigateTo({
  url: `/pages/detail/detail?data=${encodeURIComponent(JSON.stringify(complexData))}`
})

// ✅ 推荐:使用 EventChannel 进行页面间通信
uni.navigateTo({
  url: '/pages/detail/detail',
  events: {
    updateData: (data) => {
      // 处理数据更新
    }
  }
})

常见问题场景

我遇到的问题:在开发中习惯性地使用 uni.navigateTo 进行所有页面跳转,这会导致页面栈管理出现问题。

问题示例

javascript 复制代码
// ❌ 错误示例:表单页 -> 列表页 -> 详情页
// 表单页填写完成
const submitForm = () => {
  uni.navigateTo({
    url: '/pages/list/list'  // 问题:应该使用 redirectTo
  })
}

// 列表页点击 item
const goToDetail = (id) => {
  uni.navigateTo({
    url: `/pages/detail/detail?id=${id}`  // 问题:页面栈过深
  })
}

问题分析

  1. 表单页提交后,通常不需要再返回表单页,应该使用 redirectTo 替换当前页面
  2. 页面栈过深会导致返回逻辑混乱,用户体验不佳
  3. 可能导致内存占用过高(页面栈中保留过多页面)

正确的解决方案

javascript 复制代码
// ✅ 正确示例 1:表单页提交后替换为列表页
const submitForm = () => {
  uni.redirectTo({
    url: '/pages/list/list'  // 关闭表单页,打开列表页
  })
}

// ✅ 正确示例 2:如果列表页是 tabBar 页面
const submitForm = () => {
  uni.switchTab({
    url: '/pages/list/list'  // 切换到 tabBar 页面
  })
}

// ✅ 正确示例 3:详情页需要返回列表页(使用 navigateTo)
const goToDetail = (id) => {
  uni.navigateTo({
    url: `/pages/detail/detail?id=${id}`  // 可以返回列表页
  })
}

// ✅ 正确示例 4:详情页需要直接返回表单页
const goToDetail = (id) => {
  uni.navigateTo({
    url: `/pages/detail/detail?id=${id}`
  })
}

// 在详情页返回时,如果需要跳过列表页
const goBack = () => {
  uni.navigateBack({
    delta: 2  // 返回上两页(跳过列表页)
  })
}

最佳实践建议

  1. 表单提交后 → 使用 redirectToswitchTab(如果是 tabBar 页面)
  2. 需要返回的页面 → 使用 navigateTo(如详情页、编辑页)
  3. 不需要返回的页面 → 使用 redirectTo(如登录后跳转首页)
  4. 清空页面栈 → 使用 reLaunch(如退出登录)
  5. 控制页面栈深度 → 避免超过 10 层页面栈,及时使用 redirectTo 替换不需要返回的页面

页面栈深度检查

javascript 复制代码
// 检查当前页面栈深度
const pages = getCurrentPages()
console.log('当前页面栈深度:', pages.length)

// 如果页面栈过深,考虑使用 redirectTo
if (pages.length >= 10) {
  uni.redirectTo({
    url: '/pages/target/target'
  })
} else {
  uni.navigateTo({
    url: '/pages/target/target'
  })
}

总结

uni-app 的路由系统提供了灵活且强大的页面导航能力。正确理解和使用这些 API,可以帮助我们:

  1. 优化用户体验:选择合适的跳转方式和动画效果
  2. 管理页面栈:合理控制页面层级,避免内存问题
  3. 实现页面通信:通过 EventChannel 实现页面间的数据传递
  4. 提升开发效率:使用合适的路由方法简化代码逻辑

在实际开发中,建议根据具体场景选择合适的路由方法:

  • 需要返回 → 使用 navigateTo
  • 不需要返回 → 使用 redirectTo
  • 清空所有页面 → 使用 reLaunch
  • 跳转 tabBar → 使用 switchTab
  • 返回上一页 → 使用 navigateBack

希望本文能帮助你更好地理解和使用 uni-app 的路由系统!


参考文档

相关推荐
QuantumLeap丶2 小时前
《uni-app跨平台开发完全指南》- 06 - 页面路由与导航
前端·vue.js·uni-app
Sheldon一蓑烟雨任平生2 小时前
Vue3 组件库 Element Plus
vue.js·vue3·element plus·element ui·vue3 常用组件库
Kingsaj2 小时前
uni-app打包app -- 在用户首次启动 App 时,强制弹出一个“用户协议与隐私政策”的确认对话框。
服务器·ubuntu·uni-app
Vue10242 小时前
uniapp 使用renderjs 封装 video-player 视频播放器, html5视频播放器-解决视频层级、覆盖、播放卡顿
uni-app·音视频·html5
切糕师学AI2 小时前
.NET Core Web + Vue 项目集成消息推送工具SignalR
vue.js·.netcore·signalr
ttod_qzstudio2 小时前
Vue 3 Props 定义详解:从基础到进阶
前端·vue.js
钱端工程师2 小时前
uniapp封装uni.request请求,实现重复接口请求中断上次请求(防抖)
前端·javascript·uni-app
茶憶2 小时前
uni-app app移动端实现纵向滑块功能,并伴随自动播放
javascript·vue.js·uni-app·html·scss
dcloud_jibinbin2 小时前
【uniapp】解决小程序分包下的json文件编译后生成到主包的问题
前端·性能优化·微信小程序·uni-app·vue·json