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、響應式數據、組件通信等核心概念,幫助大家構建更復雜的應用邏輯。