ArkUI router 参数:详情页别假设参数一定有

举报
蓝瘦的蜕变 发表于 2026/09/15 09:45:59 2026/09/15
【摘要】 今天我们用 pushUrl 带一组参数,再在目标页用 getParams 读出来。 参数传递很常见。列表点进详情、卡片打开编辑页、搜索页带筛选条件,都绕不开它。但这里有个坑:目标页不要默认参数一定完整。 只传简单数据 Demo 里传了三个字段: 这些都是可序列化的数据。Router 参数不要塞方法、系统对象、上下文对象

ArkUI router 参数:详情页别假设参数一定有

今天我们用 pushUrl 带一组参数,再在目标页用 getParams 读出来。

参数传递很常见。列表点进详情、卡片打开编辑页、搜索页带筛选条件,都绕不开它。但这里有个坑:目标页不要默认参数一定完整。

只传简单数据

Demo 里传了三个字段:

params: new RouterParamsPayload('路由参数演示', 'ArkUI Router', 3)

这些都是可序列化的数据。Router 参数不要塞方法、系统对象、上下文对象,也不要把整块复杂业务对象直接扔过去。

目标页要做缺省展示

目标页通过:

this.getUIContext().getRouter().getParams()

拿到参数对象。然后给 titlesourcecount 都准备缺省值。这样页面从其它入口打开、参数缺失、字段没带齐时,也能正常展示。

约束也一起记住

Router 页面栈最多支持 32 个页面。参数页同样是压栈,不要把每次筛选、每次点击都做成新页面。

另外,参数是页面之间的轻量信息,不是数据库,也不是全局状态。要长期保存的数据,应该放到更合适的存储方案里。

你写详情页时,有没有遇到过参数没带齐导致页面空白?这类问题通常不是组件问题,而是路由边界没兜住。

入口页完整代码

class RouterParamsPayload {
  title: string
  source: string
  count: number

  constructor(title: string, source: string, count: number) {
    this.title = title
    this.source = source
    this.count = count
  }
}

@Entry
@Component
struct ArkUIRouterParamsDemo {
  private targetUrl: string = 'pages/arkUI/route/ArkUIRouterParamsTargetDemo'

  @Builder
  sectionTitle(title: string, desc: string) {
    Column({ space: 6 }) {
      Text(title)
        .fontSize(19)
        .fontWeight(FontWeight.Bold)
        .fontColor('#111827')
      Text(desc)
        .fontSize(13)
        .fontColor('#6B7280')
        .lineHeight(20)
    }
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('ArkUI router 参数')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('详情页别假设参数一定有')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('pushUrl 可以携带 params。目标页用 getParams 读取,但读取前要准备缺省值。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        this.sectionTitle('只传简单数据', 'params 适合放字符串、数字、布尔值这类可序列化数据,不要塞方法或系统对象。')
        Column({ space: 10 }) {
          Text('准备传给详情页的数据')
            .fontSize(14)
            .fontColor('#6B7280')
            .width('100%')
          Text('title: 路由参数演示')
            .fontSize(15)
            .fontColor('#111827')
            .width('100%')
          Text('source: ArkUI Router')
            .fontSize(15)
            .fontColor('#111827')
            .width('100%')
          Text('count: 3')
            .fontSize(15)
            .fontColor('#111827')
            .width('100%')
        }
        .width('100%')
        .padding(16)
        .borderRadius(14)
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#E5E7EB' })
        .alignItems(HorizontalAlign.Start)

        Button('带参数打开详情页')
          .fontSize(15)
          .fontColor('#FFFFFF')
          .height(44)
          .borderRadius(22)
          .backgroundColor('#0F766E')
          .padding({ left: 22, right: 22 })
          .onClick(() => {
            this.getUIContext().getRouter().pushUrl({
              url: this.targetUrl,
              params: new RouterParamsPayload('路由参数演示', 'ArkUI Router', 3)
            })
          })

        this.sectionTitle('目标页要兜底', '用户可能从别的入口进来,也可能没有拿到完整参数。详情页不要默认什么都有。')
        Text('Demo 的目标页会给 title、source、count 都准备缺省展示。这样参数缺失时,页面也不会空着。')
          .fontSize(14)
          .fontColor('#374151')
          .lineHeight(22)
          .width('100%')
          .padding(16)
          .borderRadius(14)
          .backgroundColor('#F9FAFB')
          .border({ width: 1, color: '#E5E7EB' })
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F3F4F6')
  }
}

目标页完整代码

class RouterReceivedParams {
  title?: string
  source?: string
  count?: number
}

@Entry
@Component
struct ArkUIRouterParamsTargetDemo {
  @State title: string = '未收到标题'
  @State source: string = '未收到来源'
  @State countText: string = '0'
  @State rawText: string = '{}'

  aboutToAppear(): void {
    let params = this.getUIContext().getRouter().getParams() as RouterReceivedParams
    this.title = params.title ? params.title : '未收到标题'
    this.source = params.source ? params.source : '未收到来源'
    this.countText = params.count === undefined ? '0' : `${params.count}`
    this.rawText = JSON.stringify(params)
  }

  @Builder
  infoRow(label: string, value: string) {
    Row({ space: 10 }) {
      Text(label)
        .fontSize(14)
        .fontColor('#6B7280')
        .width(72)
      Text(value)
        .fontSize(14)
        .fontColor('#111827')
        .layoutWeight(1)
    }
    .width('100%')
  }

  build() {
    Scroll() {
      Column({ space: 22 }) {
        Column({ space: 8 }) {
          Text('参数承接页')
            .fontSize(28)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
          Text('getParams 读到的是上一个页面带来的对象')
            .fontSize(16)
            .fontColor('#4B5563')
          Text('这里故意给每个字段都准备了缺省值。详情页不要假设参数一定完整。')
            .fontSize(14)
            .fontColor('#6B7280')
            .lineHeight(22)
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        Column({ space: 12 }) {
          this.infoRow('标题', this.title)
          this.infoRow('来源', this.source)
          this.infoRow('数量', this.countText)
        }
        .width('100%')
        .padding(16)
        .borderRadius(14)
        .backgroundColor('#FFFFFF')
        .border({ width: 1, color: '#E5E7EB' })

        Column({ space: 8 }) {
          Text('原始参数')
            .fontSize(16)
            .fontWeight(FontWeight.Bold)
            .fontColor('#111827')
            .width('100%')
          Text(this.rawText)
            .fontSize(13)
            .fontColor('#374151')
            .lineHeight(20)
            .width('100%')
        }
        .width('100%')
        .padding(16)
        .borderRadius(14)
        .backgroundColor('#F9FAFB')
        .border({ width: 1, color: '#E5E7EB' })
        .alignItems(HorizontalAlign.Start)

        Button('回到参数页')
          .fontSize(15)
          .fontColor('#FFFFFF')
          .height(44)
          .borderRadius(22)
          .backgroundColor('#0F766E')
          .padding({ left: 22, right: 22 })
          .onClick(() => {
            this.getUIContext().getRouter().back()
          })
      }
      .width('100%')
      .padding(24)
      .alignItems(HorizontalAlign.Start)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F3F4F6')
  }
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。