App 开发不可能只停留在单个页面,首页点条目跳详情、表单页提交后返回上一页,这些都离不开页面路由。很多新手一开始直接写多个@Entry页面,但不会用官方路由模块,要么用全局变量传参,要么页面返回数据时各种状态不同步。

网上很多旧版鸿蒙的 router 代码,在鸿蒙 7 中包名发生变化,直接复制会导入失败;还有人踩坑:页面传复杂对象丢失、返回页面数据不刷新、重复跳转同一个页面造成页面栈堆积,最后返回需要连续点好几次返回键。

今天我们系统讲解鸿蒙 7 的页面路由@ohos.router,包含基础跳转、带参数跳转、页面接收参数、返回并回传结果,还有页面栈管理,代码全部可直接运行,一并整理路由高频踩坑点。

一、路由基础概念

页面栈:系统维护的页面堆栈。打开新页面,页面入栈;点击返回,页面出栈销毁。

  • pushUrl:压入新页面,保留上一页,可以返回;
  • replaceUrl:替换当前页面,上一页直接出栈,不能返回;
  • back:页面回退,弹出栈顶页面。

误区提醒:不要用全局变量来跨页面传参。页面被销毁后全局变量容易残留脏数据,多页面共用会产生数据污染,优先使用 router 参数传递。

前置准备:配置页面路由

必须在 module.json5 中注册页面路由信息,否则跳转直接报错,找不到页面。 在 entry 模块 module.json5 -> module -> pages 数组,注册所有页面路径:

​
"pages": [
  "pages/Index",
  "pages/DetailPage",
  "pages/FormPage"
]

​

路径说明:pages 目录下面的页面文件,不需要写后缀 ets。

1. 基础页面跳转 pushUrl(可返回)

首页 Index.ets

​
import router from '@ohos.router';

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button("跳转详情页(pushUrl,可返回)")
        .onClick(() => {
          // 跳转到详情页面
          router.pushUrl({
            url: "pages/DetailPage"
          })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

​
关键说明

router.pushUrl:新页面入栈,打开详情页后,点击返回按键,回到当前首页。

2. replaceUrl 替换当前页面(不可返回)

适合场景:登录成功后进入首页,不希望返回登录页。

​
Button("替换页面 replaceUrl")
  .onClick(() => {
    router.replaceUrl({
      url: "pages/FormPage"
    })
  })

​

区别:replaceUrl 会把当前页面从页面栈移除,新页面替换上来,无法返回上一页。

二、跳转时传递参数,目标页面接收参数

pushUrl 的 params 字段用来携带参数,支持字符串、数字、简单对象。 Index.ets(发送页面)

​
import router from '@ohos.router';

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button("跳转详情,携带参数")
        .onClick(() => {
          router.pushUrl({
            url: "pages/DetailPage",
            params: {
              id: 1001,
              title: "订单详情",
              desc: "这是从首页传过来的数据"
            }
          })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

​

DetailPage.ets(接收页面)

​
import router from '@ohos.router';

@Entry
@Component
struct DetailPage {
  @State pageId: number = 0;
  @State pageTitle: string = "";
  @State pageDesc: string = "";

  aboutToAppear() {
    // 获取路由传递过来的参数
    const params = router.getParams() as { id: number, title: string, desc: string };
    if(params){
      this.pageId = params.id;
      this.pageTitle = params.title;
      this.pageDesc = params.desc;
    }
  }

  build() {
    Column() {
      Text(`ID:${this.pageId}`).fontSize(20)
      Text(`标题:${this.pageTitle}`).fontSize(20).margin({top:8})
      Text(`描述:${this.pageDesc}`).fontSize(16).margin({top:8})
      
      Button("返回首页")
        .margin({top:30})
        .onClick(()=>{
          router.back()
        })
    }
    .padding(20)
    .width('100%')
    .height('100%')
  }
}

​
重点讲解
  1. params:载体,放要传递的数据;
  2. router.getParams():在目标页面aboutToAppear生命周期获取参数;
  3. 类型断言as,做类型约束,TS 语法提示更友好。

⚠️坑提醒:不要传递函数、复杂类实例,路由参数仅支持可序列化数据(数字、字符串、普通对象、数组)。传递函数会丢失。

三、页面返回,回传数据给上一页

业务场景:打开表单页面,填写内容,提交返回,把填写结果传回首页。 思路:pushUrl 增加success回调,子页面 back 的时候携带参数,在上一页 success 回调接收返回数据。

Index.ets

​
import router from '@ohos.router';

@Entry
@Component
struct Index {
  @State resultText: string = "等待表单返回数据";

  build() {
    Column() {
      Text(this.resultText).fontSize(20).margin({bottom:20})
      Button("打开表单页,等待返回结果")
        .onClick(() => {
          router.pushUrl({
            url: "pages/FormPage"
          }, (err) => {
            // 页面关闭返回时,在这里拿到回传参数
            const res = router.getParams() as { msg:string, content:string }
            if(res){
              this.resultText = `表单返回:${res.content}`
            }
          })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .padding(20)
  }
}

​

FormPage.ets(表单页面)

​
import router from '@ohos.router';

@Entry
@Component
struct FormPage {
  @State inputStr:string = "";

  build() {
    Column() {
      TextInput({text:this.inputStr, placeholder:"输入内容,提交带回首页"})
        .padding(10)
        .border({width:1, color:"#ccc"})
        .width('90%')
      
      Button("提交并返回")
        .margin({top:20})
        .onClick(()=>{
          // back携带回传参数
          router.back({
            params:{
              msg:"表单提交成功",
              content: this.inputStr
            }
          })
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .padding(20)
  }
}

​

四、页面栈管理:清空页面栈

场景:登录成功,跳转首页,并且清空页面栈,不能返回到登录页。

​
router.pushUrl({
  url: "pages/Index"
}, undefined, router.RouterMode.Single, ()=>{
  // 跳转成功后清空页面栈
  router.clear()
})

​
  • router.clear():清空整个页面栈,当前页面作为唯一页面。

五、路由高频踩坑汇总

坑 1:module.json5 没有注册页面路径

现象:调用 pushUrl 直接报错,页面无法打开。 解决:pages 数组添加页面路径,路径名称大小写保持一致。

坑 2:路由 params 传递函数、复杂对象

params 只能传序列化数据,函数、类实例传过去直接变成 undefined。

坑 3:快速重复点击按钮,多次 push 同一个页面

快速点击,短时间多次触发 pushUrl,页面栈堆积多个相同页面,返回需要多次点击。 解决:加按钮防抖标记,短时间禁止重复跳转。

坑 4:getParams 获取到旧缓存参数

页面多次跳转复用,getParams 拿到上一次残留参数。 解决:拿到参数后手动清空,或者每次判断参数是否有效。

坑 5:返回参数接收时机写错

不要在 build 里面直接获取返回参数,要在 pushUrl 的 success 回调里面接收。

六、路由 API 选型速查表

API作用适用场景
router.pushUrl入栈新页面,可以返回详情页、表单页,需要返回上一页
router.replaceUrl替换当前页面,销毁上一页登录跳转首页,引导页
router.back()页面回退,支持携带返回参数子页面返回,回传数据
router.getParams()获取路由携带参数目标页面读取传入数据
router.clear()清空页面栈登录成功,清除登录页面

结尾总结

鸿蒙 7 页面路由使用@ohos.router模块,页面跳转本质是页面栈的入栈和出栈。

  1. 所有页面必须在 module.json5 的 pages 数组注册,否则跳转失败;
  2. pushUrl 打开新页面,支持 params 向前传参;back 可以携带 params 回传数据给上一页;
  3. pushUrl 适合需要返回的页面;replaceUrl 适合不需要返回的页面;
  4. 路由参数只允许可序列化数据,不能传函数;
  5. 注意防止快速重复点击造成页面栈堆积。

实操指南

新建两个页面:列表页和编辑页。列表点击条目,把 id 传到编辑页;编辑页修改文字,提交返回,将新文字回传给列表页并刷新列表展示。

Logo

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

更多推荐