为一篇讲解 HarmonyOS7 router 跳详情页时不要传复杂对象的技术文章绘制一张 sket

前言

详情页跳转最省事的写法,是把列表里的整条对象直接传过去。刚开始确实方便,但项目一大就会出问题:对象字段变了、页面刷新了、来源页面不止一个了,详情页就越来越依赖上个页面。

HarmonyOS7 用 router 跳转时,我更建议只传稳定参数,比如 articleId,最多再带一个预览标题。路由参数只负责识别目标内容,不负责搬运整份业务数据。

为什么这个问题经常被写乱

router 跳详情页别传复杂对象 这类内容很容易被写成“代码能跑就算讲完了”,但对初学者来说,这恰恰是最不够的地方。真正让人卡住的,往往不是某个组件名记不住,而是不知道这段代码为什么要这样拆、状态为什么要这样放、以后需求变化时应该从哪里改。

所以这篇文章不只想给你一个能跑的例子,更想把背后的判断过程讲清楚。你只要把这个判断过程吃透,后面自己改页面、补需求、查问题时,心里会稳很多。

为一篇 HarmonyOS7 router 教程绘制一张 sketch-notes 风格的对比图,主

参数应该轻一点

文章列表到详情页,可以这么拆。

参数是否建议传说明
articleId建议小、稳定、可重新请求
previewTitle可选适合做过渡展示
完整文章对象不建议体积大,字段变化影响跳转
评论列表不建议应该由详情页自己加载

这样设计后,详情页不关心用户从首页、收藏页还是搜索页进入,它只需要拿到 articleId

先把页面目标想清楚

在真正写代码之前,先别急着盯着 API。更有用的做法是先想清楚:这个页面到底想解决什么问题,用户最在意的反馈是什么,哪些状态必须一直保持一致。

当你先把这条主线想明白,再回头看组件和状态设计,很多选择都会顺理成章。对小白来说,这一步尤其重要,因为它能帮你从“照着抄”慢慢过渡到“看得懂、改得动”。

完整 ArkTS 示例

import { router } from '@kit.ArkUI'

interface ArticleCard {
  id: number
  title: string
  summary: string
}

@Entry
@Component
struct ArticleListPage {
  private articles: ArticleCard[] = [
    { id: 701, title: 'HarmonyOS7 状态刷新排查', summary: '从数组更新和对象赋值说起。' },
    { id: 702, title: 'ArkUI 列表性能笔记', summary: 'List、ForEach 和 LazyForEach 的取舍。' }
  ]

  private openDetail(article: ArticleCard): void {
    router.pushUrl({
      url: 'pages/ArticleDetailPage',
      params: {
        articleId: article.id,
        previewTitle: article.title
      }
    })
  }

  build() {
    List({ space: 10 }) {
      ForEach(this.articles, (item: ArticleCard) => {
        ListItem() {
          Column({ space: 6 }) {
            Text(item.title)
              .fontSize(17)
              .fontWeight(FontWeight.Medium)
            Text(item.summary)
              .fontSize(13)
              .fontColor('#666666')
          }
          .alignItems(HorizontalAlign.Start)
          .padding(14)
          .backgroundColor(Color.White)
          .borderRadius(10)
        }
        .onClick(() => this.openDetail(item))
      }, (item: ArticleCard) => item.id.toString())
    }
    .padding(16)
    .backgroundColor('#F5F7FA')
  }
}

@Component
struct ArticleDetailContent {
  @Prop articleId: number
  @Prop previewTitle: string

  build() {
    Column({ space: 12 }) {
      Text(this.previewTitle)
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
      Text(`详情页拿到 articleId=${this.articleId} 后,再去请求或读取完整文章。`)
        .fontSize(14)
        .fontColor('#666666')
    }
    .padding(16)
  }
}

为一篇讲解 HarmonyOS7 router 详情页数据恢复思路的文章绘制一张 sketch-no

把关键代码一段段拆开

openDetail() 只传 articleIdpreviewTitle。前者是详情页恢复数据的关键,后者只是过渡展示,不能当作详情页唯一数据源。

列表页仍然可以用完整对象渲染卡片,但路由层不需要知道全部字段。这样文章卡片以后新增封面、标签、作者信息,都不会影响跳转契约。

详情页拿到 articleId 后,可以从缓存、状态管理或接口里恢复完整数据。页面重新进入时也有稳定依据,不依赖上一页还在内存里。

复杂对象为什么麻烦

复杂对象最大的风险不是“传不传得过去”,而是边界变模糊。详情页开始依赖列表页的对象结构,搜索页也要拼一样的对象,收藏页也要拼一样的对象。只要某个入口少一个字段,详情页就可能出现空数据。

如果确实想减少详情页白屏,可以传轻量预览字段,比如标题或封面。它们只用于过渡,详情内容仍然以详情页加载结果为准。

新手最容易踩的坑

这一类示例最容易让人产生错觉:界面出来了,就以为已经掌握了。其实真正容易出问题的地方,通常都在效果之外,比如状态有没有收拢、失败后怎么兜底、以后要扩展时会不会牵一发动全身。

所以你练这篇内容时,别只看“现在能不能跑”,还要继续看“以后好不好改”。能把这个习惯养起来,你写出来的页面会比单纯照着示例拼出来的页面稳很多。

放进真实项目还要补什么

示例代码的重点是把核心思路讲明白,所以很多工程化细节会故意省掉。真正落到项目里时,你通常还要继续补接口联动、异常处理、边界保护、资源抽离,以及和其他页面状态之间的配合。

比较稳的做法是分三步走:先把结构和职责立住,再把真实业务接进去,最后再优化视觉和交互体验。这样改出来的页面不只是“能演示”,而是真的更接近可以长期维护的业务代码。

写在最后

router 参数越轻,页面越独立。把路由当成“带着 id 去另一个页面”,而不是“把整个对象塞过去”,后面做刷新、分享、收藏入口都会轻松很多。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐