第26次:源码学习模块

本文讲解项目里的源码学习功能,对应核心文件是 SourceCodePage.etsSourceCodeDetailPage.ets,数据来自 SourceCodeData.etsSourceCodeDetailData.ets。这一部分不只是列标题,而是把知识分类、章节概览、详情内容、源码片段和参考资料串成了一套完整的阅读体验。


先看整体结构

源码学习模块分成两层:

  • 概览层:SourceCodePage
  • 详情层:SourceCodeDetailPage

概览层负责分类和章节列表,详情层负责深度阅读和代码复制。

SourceCodePage

分类横向标签

章节列表

展开摘要内容

查看完整内容

SourceCodeDetailPage

章节信息卡片

详细小节

源码片段

参考资料


一、为什么源码学习要拆成“概览页 + 详情页”

源码学习内容通常有一个特点:信息密度高。如果一进页面就把所有细节铺满,用户会很容易被淹没。当前项目采用两层结构是非常合理的:

  • 概览页:帮助用户快速浏览、筛选和决定读哪一章
  • 详情页:进入后再深入看完整内容、源码和参考链接

这和课程列表 / 模块详情 / 课时详情的思路很像,本质上仍然是“摘要层 + 深读层”的设计模式。


二、概览页 SourceCodePage 的设计重点是什么

概览页的核心元素有三个:

  1. 顶部标题栏
  2. 分类横向标签
  3. 章节可展开列表

分类标签

使用横向滚动的标签条,让用户在不同源码主题之间切换。每个标签既有图标,也有名称,这样比纯文字更容易识别。

分类切换本身并不复杂,但这段真实代码很值得跟着读一遍,因为它把“切换标签”和“重置列表展开状态”连在了一起:

ForEach(this.categories, (cat: SourceCodeCategory) => {
  Column() {
    Text(cat.icon).fontSize(20)
    Text(cat.name).fontSize(11)
      .fontColor(this.selectedCategory === cat.id ?
        '#ffffff' : (this.isDarkMode ? '#e0e6eb' : '#495057'))
      .margin({ top: 4 })
  }
  .padding({ left: 12, right: 12, top: 8, bottom: 8 })
  .backgroundColor(this.selectedCategory === cat.id ?
    (this.isDarkMode ? '#61DAFB' : '#0077b6') :
    (this.isDarkMode ? '#282c34' : '#ffffff'))
  .borderRadius(12)
  .onClick(() => {
    this.selectedCategory = cat.id;
    this.chapters = SourceCodeData.getChaptersByCategory(cat.id);
    this.expandedChapter = '';
  })
})

章节列表

每章都展示:

  • 难度徽章
  • 章节序号
  • 标题
  • 描述

点击后还能展开,直接预览章节内容、代码示例和关键要点。这个“先展开,再决定要不要看详情”的体验很适合学习型阅读。


三、详情页为什么信息层次这么多

进入 SourceCodeDetailPage 后,页面会按顺序展示:

  • 章节基本信息卡片
  • 详细小节列表
  • 源码区
  • 参考资料区

这实际上对应的是一个非常完整的学习节奏:

  1. 我先知道这一章讲什么
  2. 我再按小节系统阅读
  3. 然后看源码原文
  4. 最后顺着参考资料继续延展

这样的结构说明当前项目不是简单“放一份源码文本”,而是想把源码阅读做成一种有引导的学习过程。

详情页拿数据的入口也很清楚,先读参数,再查章节,再查详情:

aboutToAppear(): void {
  const params = router.getParams() as RouterParams;
  if (params?.chapterId) {
    this.chapter = SourceCodeData.getChapterById(params.chapterId) || null;
    this.detail = SourceCodeDetailData.getDetail(params.chapterId) || null;
  }
  this.isLoading = false;
}

四、源码区为什么同时支持滚动和复制

源码文本通常很长,所以详情页在源码区里做了两件很必要的事:

  • 横向/局部滚动
  • 一键复制

这两个功能非常实用:

  • 滚动保证长代码不会把布局撑坏
  • 复制保证用户可以把代码带出去分析、对比或实验

copyToClipboard() 这里复用了系统剪贴板和 Toast 提示,这和前面 CodeBlock 组件的设计思路是一致的。也就是说,项目在“代码可带走”这件事上是有统一意识的。

SourceCodeDetailPage.ets 里,复制逻辑就是下面这样接到系统能力上的:

private copyToClipboard(text: string): void {
  const pasteboardData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, text);
  const systemPasteboard = pasteboard.getSystemPasteboard();
  systemPasteboard.setData(pasteboardData, (err) => {
    if (err) {
      promptAction.showToast({ message: '复制失败', duration: 1500 });
    } else {
      promptAction.showToast({ message: '已复制到剪贴板', duration: 1500 });
    }
  });
}

五、参考资料区为什么不能省

很多源码学习页只做到“我来解释一下”,但当前项目还加了参考资料区,这一步其实很重要。因为真正的源码学习往往不是一次就结束的,用户看完概览后,还会想:

  • 有没有官方文档
  • 有没有原仓库
  • 有没有延伸文章

详情页里的参考资料区恰恰承担了这种“继续深入”的入口作用。教程型产品只讲自己的理解是不够的,最好还能给用户留下继续探索的路径。


六、这一模块和普通课程模块有什么不同

源码学习模块虽然也属于学习内容,但和普通课程模块还是有明显差异:

  • 普通课程强调从零到一的教学引导
  • 源码学习强调结构理解和阅读能力

因此它的页面设计也更偏“阅读器”和“知识图谱”,而不是“课时推进器”。你会发现这里没有完成按钮、没有收藏星标、没有课时进度,而是更强调:

  • 分类浏览
  • 展开预览
  • 深入详情
  • 复制代码
  • 参考链接

这说明同一个应用中,不同类型内容应该采用不同的交互模型。


七、图文结合看一下示例项目素材

源码学习本身没有独立截图资源,但它和项目整体视觉风格是统一的。你可以顺便参考项目中示例资源的设计呈现方式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上面这类素材不是源码学习页面本身的截图,但它能帮助你理解这个项目整体是如何把“知识内容”和“视觉表达”结合起来的。


八、自己实操时建议这样走

  1. 打开源码学习页,先切换几个分类标签。
  2. 展开任意章节,观察摘要、代码示例和关键要点。
  3. 点击“查看完整内容”进入详情页。
  4. 测试源码区滚动和复制是否正常。
  5. 再点几条参考资料,检查链接信息是否完整。

只要这条路径走一遍,你就能非常清楚源码学习模块是如何组织内容的。


九、本篇常见坑

1. 把源码学习页做成纯文本大长页

这样用户几乎没有办法快速筛选内容。

2. 没有概览层直接跳详情

会让入口太重,学习成本变高。

3. 源码不支持复制

学习型页面中,代码复制几乎是刚需。

4. 缺少参考资料

用户看完之后没有继续深入的路径,学习会被强行截断。


本篇小结

源码学习模块真正值得学的,不只是“有一页源码详情”,而是它建立了一套很清楚的阅读路径:

  • 先分类
  • 再浏览
  • 再展开
  • 再深读
  • 最后延展

这种结构非常适合做知识密度高的内容模块,也很适合鸿蒙项目中的教学型页面设计。


课后练习

  1. 比较 SourceCodePageModuleDetail 的结构差异,说明为什么一个更像“阅读目录”,另一个更像“课程目录”。
  2. 思考如果你要给源码详情页增加“加入收藏”功能,应该收藏章节 ID 还是源码文件路径。
  3. 列出详情页中哪几个区块最适合后续抽成通用组件。
Logo

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

更多推荐