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、响应式数据、组件通信等核心概念,帮助大家构建更复杂的应用逻辑。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐