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個tab
  • pagePath必須與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在鴻蒙平台下的頁面路由與導航系統的核心知識:

  1. 路由配置:通過pages.json管理頁面路徑、全局樣式和TabBar
  2. 跳轉方法navigateToredirectToreLaunchswitchTabnavigateBack五種跳轉方式
  3. 參數傳遞:URL傳參、全局變量、事件總線三種傳參方案
  4. TabBar配置:底部導航欄的靜態配置和動態修改
  5. 頁面棧管理getCurrentPages()獲取頁面棧信息
  6. 生命週期:頁面特有的生命週期鈎子函數
  7. 實戰案例:電商應用的完整導航系統實現

關鍵要點

  • 頁面棧深度限制為10層,需要合理設計跳轉層級
  • TabBar頁面跳轉必須使用switchTab方法
  • 複雜數據傳遞建議使用事件總線或全局狀態管理
  • 鴻蒙平台支持原生導航欄控制,性能更優

下一篇文章,我們將深入講解uniapp在鴻蒙平台下的數據綁定與狀態管理,包括Vue3組合式API、響應式數據、組件通信等核心概念,幫助大家構建更復雜的應用邏輯。