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

目录

  • 概述
  • 路由 API 详解
    • uni.navigateTo - 保留当前页面跳转
    • uni.redirectTo - 关闭当前页面跳转
    • uni.reLaunch - 关闭所有页面跳转
    • uni.switchTab - 跳转到 tabBar 页面
    • uni.navigateBack - 返回上一页
  • 页面间通信 - EventChannel
  • 窗口动画配置
  • 注意事项和最佳实践
  • 总结

概述

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

路由 API 详解

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

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

适用场景

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

参数说明

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

代码示例

// 在起始页面跳转到 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
  }
}

传递复杂参数

// 传递对象参数(需要序列化)
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 参数)

代码示例

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

与 navigateTo 的区别

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

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

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

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

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

适用场景

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

代码示例

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

uni.switchTab - 跳转到 tabBar 页面

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

适用场景

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

重要提示

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

代码示例

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

pages.json 配置示例

{
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页"
      },
      {
        "pagePath": "pages/user/user",
        "text": "我的"
      }
    ]
  }
}

uni.navigateBack - 返回上一页

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

参数说明

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

代码示例

// 返回上一页
uni.navigateBack()

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

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

实际应用场景

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

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

页面间通信 - EventChannel

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

EventChannel 方法

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

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

完整示例

// 源页面 - 发送数据
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: '来自详情页的数据'
    })
  }
}

窗口动画配置

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

API 配置

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

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

组件配置

<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 配置

{
  "style": {
    "app-plus": {
      "animationType": "fade-in",
      "animationDuration": 300
    }
  }
}

支持的动画类型

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

注意事项和最佳实践

1. 路由限制

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

2. 页面栈管理

// 注意页面栈的层级
// 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() 导航到浏览器的其他历史记录。

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

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

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

5. 参数传递最佳实践

//  推荐:简单参数使用 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) => {
      // 处理数据更新
    }
  }
})

6. 避免过度使用 navigateTo 导致页面栈问题

常见问题场景

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

问题示例

//  错误示例:表单页 -> 列表页 -> 详情页
// 表单页填写完成
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. 可能导致内存占用过高(页面栈中保留过多页面)

正确的解决方案

//  正确示例 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 替换不需要返回的页面

页面栈深度检查

// 检查当前页面栈深度
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 的路由系统!


参考文档

  • uni-app 页面路由文档
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]