uniapp开发鸿蒙:页面路由与导航实战
路由配置:通过pages.json管理页面路径、全局样式和TabBar跳转方法navigateToredirectToreLaunchswitchTab五种跳转方式参数传递:URL传参、全局变量、事件总线三种传参方案TabBar配置:底部导航栏的静态配置和动态修改页面栈管理获取页面栈信息生命周期:页面特有的生命周期钩子函数实战案例:电商应用的完整导航系统实现关键要点页面栈深度限制为10层,需要合理
uniapp开发鸿蒙:页面路由与导航实战
引入:多页面应用的核心
在前两篇文章中,我们学习了uniapp鸿蒙开发环境的搭建和Flex布局基础。今天,我们将深入探讨uniapp在鸿蒙平台下的页面路由与导航系统,这是构建多页面应用的核心能力。
uniapp的路由系统基于Vue.js实现,通过维护页面栈来管理应用内不同页面之间的跳转关系。在鸿蒙平台,这套路由系统会映射到鸿蒙原生导航机制,实现跨平台统一的页面管理体验。
一、pages.json路由配置详解
1.1 基础页面配置
pages.json是uniapp的核心配置文件,负责管理页面路由、窗口样式和导航栏设置。所有页面都必须在这里注册才能正常访问。
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"navigationBarBackgroundColor": "#FFFFFF",
"navigationBarTextStyle": "black"
}
},
{
"path": "pages/detail/detail",
"style": {
"navigationBarTitleText": "详情页"
}
}
]
}
关键配置项说明:
path:页面路径,相对于项目根目录,省略.vue扩展名navigationBarTitleText:导航栏标题文字navigationBarBackgroundColor:导航栏背景颜色navigationBarTextStyle:导航栏文字颜色,支持black/white
1.2 全局样式配置
globalStyle用于设置所有页面的默认样式,优先级低于页面级样式配置:
{
"globalStyle": {
"navigationBarBackgroundColor": "#3b82f6",
"navigationBarTextStyle": "white",
"navigationBarTitleText": "智能商城",
"backgroundColor": "#F8F8F8",
"enablePullDownRefresh": false,
"backgroundTextStyle": "dark",
"onReachBottomDistance": 50
}
}
1.3 分包加载配置
当项目较大时,可以通过分包优化加载速度。分包页面需要在subPackages中配置:
{
"subPackages": [
{
"root": "pagesA",
"pages": [
{
"path": "list/list",
"style": {
"navigationBarTitleText": "列表页"
}
}
]
}
]
}
二、页面跳转方法详解
uniapp提供了多种页面跳转API,每种方法对应不同的页面栈管理策略。
2.1 uni.navigateTo(保留当前页跳转)
保留当前页面,跳转到应用内的某个页面,使用uni.navigateBack可以返回到原页面。
// 跳转到详情页并传递参数
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=商品名称',
success: () => {
console.log('跳转成功')
},
fail: (err) => {
console.error('跳转失败', err)
}
})
特性说明:
- ✅ 保留当前页面(压入页面栈)
- ⚠️ 小程序端页面栈最多10层
- 🎯 适用于需要返回的次级页面(如商品详情)
2.2 uni.redirectTo(关闭当前页跳转)
关闭当前页面,跳转到应用内的某个页面。
// 登录后替换首页
uni.redirectTo({
url: '/pages/home/home'
})
特性说明:
- 🔥 关闭当前页面(替换栈顶页面)
- 📌 无法跳转到TabBar页面
- 💡 典型场景:登录页替换首页
2.3 uni.reLaunch(重启应用跳转)
关闭所有页面,打开到应用内的某个页面。
// 强制跳转首页
uni.reLaunch({
url: '/pages/index/index'
})
特性说明:
- 💥 关闭所有页面打开新页面
- 🛠️ 可用于强制跳转首页
- ⚠️ 所有页面生命周期触发onUnload
2.4 uni.switchTab(TabBar切换)
跳转到tabBar页面,并关闭其他所有非tabBar页面。注意:只有这个方法能跳转到TabBar页面。
// 切换到底部导航栏
uni.switchTab({
url: '/pages/cart/cart'
})
特性说明:
- 🎯 专用于TabBar页面切换
- 🚫 不支持传递参数
- ⚡ 触发页面的onShow而非onLoad
2.5 uni.navigateBack(返回上级页面)
关闭当前页面,返回上一页面或多级页面。
// 返回1层
uni.navigateBack()
// 返回指定层数
uni.navigateBack({
delta: 2 // 返回上上级
})
特性说明:
- 🔙 基于页面栈的后退机制
- 📦 可通过getCurrentPages()获取当前页面栈信息
- ⚠️ delta不能超过页面栈深度
三、页面传参与数据接收
3.1 URL Query传参(最常用)
通过URL拼接参数传递数据,在目标页面的onLoad生命周期中接收:
发送参数:
uni.navigateTo({
url: '/pages/detail/detail?id=123&name=张三&price=99.9'
})
接收参数:
export default {
onLoad(options) {
console.log(options.id) // 123
console.log(options.name) // "张三"
console.log(options.price) // "99.9"
// 将参数赋值给data
this.productId = options.id
this.productName = decodeURIComponent(options.name)
}
}
注意事项:
- 参数会自动解析为字符串类型
- 中文等特殊字符需要编码处理
- 小程序端URL长度有限制(约1KB)
- 复杂对象需要手动序列化
3.2 全局变量传参
通过getApp().globalData实现跨页面数据共享:
定义全局变量(app.vue):
export default {
globalData: {
userInfo: null,
token: ''
}
}
设置数据:
const app = getApp()
app.globalData.userInfo = {
id: 1,
name: '张三',
avatar: '/static/avatar.png'
}
获取数据:
const app = getApp()
console.log(app.globalData.userInfo)
3.3 事件总线传参
通过uni的事件机制实现页面间通信,适合复杂数据传递场景:
发送页面:
// 跳转前设置数据
uni.$emit('productDetail', {
id: 123,
name: '商品名称',
price: 199.9,
images: ['/static/product1.jpg', '/static/product2.jpg']
})
uni.navigateTo({
url: '/pages/detail/detail'
})
接收页面:
export default {
data() {
return {
product: null
}
},
onLoad() {
// 监听事件
uni.$on('productDetail', (data) => {
this.product = data
})
},
onUnload() {
// 移除事件监听,避免内存泄漏
uni.$off('productDetail')
}
}
四、TabBar底部导航栏配置
4.1 基础配置
TabBar是移动端应用常见的底部导航栏组件,在pages.json中配置:
{
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"backgroundColor": "#ffffff",
"borderStyle": "black",
"height": "50px",
"fontSize": "10px",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png",
"text": "首页"
},
{
"pagePath": "pages/category/category",
"iconPath": "static/tabbar/category.png",
"selectedIconPath": "static/tabbar/category-active.png",
"text": "分类"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart-active.png",
"text": "购物车"
},
{
"pagePath": "pages/mine/mine",
"iconPath": "static/tabbar/mine.png",
"selectedIconPath": "static/tabbar/mine-active.png",
"text": "我的"
}
]
}
}
配置要点:
list数组最少配置2个,最多配置5个tabpagePath必须与pages数组中配置的路径一致- 图标推荐尺寸:81px×81px,PNG格式
- 页面展现过一次后就保留在内存中,再次切换只会触发
onShow
4.2 动态修改TabBar
uniapp提供了动态修改TabBar的API:
// 修改单个tab项
uni.setTabBarItem({
index: 0, // tabBar的哪一项,从左边算起
text: '首页',
iconPath: 'static/tabbar/home-new.png',
selectedIconPath: 'static/tabbar/home-new-active.png'
})
// 修改整体样式
uni.setTabBarStyle({
color: '#999999',
selectedColor: '#FF0000',
backgroundColor: '#FFFFFF',
borderStyle: 'black'
})
// 显示红点提示
uni.showTabBarRedDot({
index: 2
})
// 隐藏TabBar
uni.hideTabBar({
animation: true
})
// 显示TabBar
uni.showTabBar({
animation: true
})
五、页面栈管理与生命周期
5.1 获取页面栈信息
通过getCurrentPages()可以获取当前页面栈的实例列表:
const pages = getCurrentPages()
console.log('当前页面栈:', pages)
// 获取当前页面实例
const currentPage = pages[pages.length - 1]
// 获取上一页实例
const prevPage = pages[pages.length - 2]
// 返回上一页并传递数据
prevPage.$vm.setData({
refresh: true
})
uni.navigateBack()
注意事项:
- 页面栈在热更新时可能重置,不建议直接修改页面栈
- 小程序端页面栈最大深度为10层
- 可以通过
pages.length判断当前栈深度
5.2 页面生命周期
uniapp页面生命周期与Vue组件生命周期类似,但增加了页面特有的钩子函数:
| 生命周期 | 触发时机 | 说明 |
|---|---|---|
| onLoad | 页面加载时 | 接收页面参数 |
| onShow | 页面显示时 | 每次页面显示都触发 |
| onReady | 页面初次渲染完成 | 页面初次渲染完成 |
| onHide | 页面隐藏时 | 页面跳转或被覆盖 |
| onUnload | 页面卸载时 | 页面被关闭或销毁 |
示例:
export default {
onLoad(options) {
console.log('页面加载,参数:', options)
},
onShow() {
console.log('页面显示')
},
onReady() {
console.log('页面初次渲染完成')
},
onHide() {
console.log('页面隐藏')
},
onUnload() {
console.log('页面卸载')
}
}
六、实战案例:电商应用导航系统
6.1 页面结构设计
{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页",
"enablePullDownRefresh": true
}
},
{
"path": "pages/category/category",
"style": {
"navigationBarTitleText": "分类"
}
},
{
"path": "pages/cart/cart",
"style": {
"navigationBarTitleText": "购物车"
}
},
{
"path": "pages/mine/mine",
"style": {
"navigationBarTitleText": "我的"
}
},
{
"path": "pages/product/detail",
"style": {
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/order/list",
"style": {
"navigationBarTitleText": "订单列表"
}
},
{
"path": "pages/order/detail",
"style": {
"navigationBarTitleText": "订单详情"
}
}
],
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#FF6B35",
"backgroundColor": "#FFFFFF",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png",
"text": "首页"
},
{
"pagePath": "pages/category/category",
"iconPath": "static/tabbar/category.png",
"selectedIconPath": "static/tabbar/category-active.png",
"text": "分类"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "static/tabbar/cart.png",
"selectedIconPath": "static/tabbar/cart-active.png",
"text": "购物车"
},
{
"pagePath": "pages/mine/mine",
"iconPath": "static/tabbar/mine.png",
"selectedIconPath": "static/tabbar/mine-active.png",
"text": "我的"
}
]
}
}
6.2 页面跳转逻辑实现
首页跳转到商品详情:
// 首页商品点击事件
goToProductDetail(product) {
uni.navigateTo({
url: `/pages/product/detail?id=${product.id}&name=${encodeURIComponent(product.name)}`
})
}
商品详情页接收参数:
export default {
data() {
return {
productId: '',
productName: '',
productInfo: null
}
},
onLoad(options) {
this.productId = options.id
this.productName = decodeURIComponent(options.name)
// 根据ID获取商品详情
this.getProductDetail()
},
methods: {
getProductDetail() {
// 调用接口获取商品详情
console.log('获取商品详情,ID:', this.productId)
},
// 加入购物车
addToCart() {
// 加入购物车逻辑
uni.showToast({
title: '加入购物车成功',
icon: 'success'
})
// 返回上一页
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
}
}
购物车页动态更新TabBar:
export default {
onLoad() {
// 页面加载时清除购物车红点
uni.hideTabBarRedDot({
index: 2 // 购物车tab的索引
})
},
onShow() {
// 页面显示时更新购物车数量
this.updateCartCount()
},
methods: {
updateCartCount() {
// 获取购物车数量
const cartCount = this.getCartCount()
if (cartCount > 0) {
// 显示购物车数量
uni.setTabBarBadge({
index: 2,
text: cartCount.toString()
})
} else {
// 隐藏购物车数量
uni.removeTabBarBadge({
index: 2
})
}
}
}
}
七、跨平台注意事项
7.1 平台差异对比
| 特性 | 微信小程序 | H5 | App | 鸿蒙 |
|---|---|---|---|---|
| 页面栈最大深度 | 10层 | 无限制 | 10层 | 10层 |
| 原生导航栏支持 | ✔️ | ✔️ | ✔️ | ✔️ |
| 路由传参方式 | URL | URL | URL | URL |
| 页面预加载 | ✔️ | ✔️ | ✔️ | ✔️ |
| 动态修改导航栏 | API | CSS | 原生API | API |
7.2 鸿蒙平台特有配置
在鸿蒙平台,可以通过app-harmony节点进行特殊配置:
{
"globalStyle": {
"app-harmony": {
"navigationBarBackgroundColor": "#3b82f6",
"navigationBarTextStyle": "white",
"backgroundColor": "#F8F8F8",
"usingComponents": {
"custom-nav": "/components/custom-nav"
}
}
}
}
总结
通过本篇文章的学习,我们掌握了uniapp在鸿蒙平台下的页面路由与导航系统的核心知识:
- 路由配置:通过
pages.json管理页面路径、全局样式和TabBar - 跳转方法:
navigateTo、redirectTo、reLaunch、switchTab、navigateBack五种跳转方式 - 参数传递:URL传参、全局变量、事件总线三种传参方案
- TabBar配置:底部导航栏的静态配置和动态修改
- 页面栈管理:
getCurrentPages()获取页面栈信息 - 生命周期:页面特有的生命周期钩子函数
- 实战案例:电商应用的完整导航系统实现
关键要点:
- 页面栈深度限制为10层,需要合理设计跳转层级
- TabBar页面跳转必须使用
switchTab方法 - 复杂数据传递建议使用事件总线或全局状态管理
- 鸿蒙平台支持原生导航栏控制,性能更优
下一篇文章,我们将深入讲解uniapp在鸿蒙平台下的数据绑定与状态管理,包括Vue3组合式API、响应式数据、组件通信等核心概念,帮助大家构建更复杂的应用逻辑。
更多推荐




所有评论(0)