HarmonyOS PC 应用,先做文档模型


子玥酱 (掘金 / 知乎 / CSDN / 简书 同名)

大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩‍💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。

我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,

在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。

技术方向: 前端 / 跨端 / 小程序 / 移动端工程化 内容平台: 掘金、知乎、CSDN、简书 创作特点: 实战导向、源码拆解、少空谈多落地 **文章状态:**长期稳定更新,大量原创输出

我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在"API 怎么用",而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。

子玥酱 · 前端成长记录官 ✨

👋 如果你正在做前端,或准备长期走前端这条路

📚 关注我,第一时间获取前端行业趋势与实践总结

🎁 可领取 11 类前端进阶学习资源 (工程化 / 框架 / 跨端 / 面试 / 架构)

💡 一起把技术学"明白",也用"到位"

持续写作,持续进阶。

愿我们都能在代码和生活里,走得更稳一点 🌱

文章目录

引言

在上一篇里我们已经达成一个共识:

在 HarmonyOS PC 场景下,

页面不再是核心,
文档才是。

但很多人在真正落地时,会立刻卡在一个现实问题上:

文档模型,

到底是一个类?

一套状态?

还是一个复杂框架?

如果你一开始就把"文档模型"想得太大,那这一步几乎一定会走偏。

常见误解:文档模型 ≠ 文件读写

很多人第一次听到"文档模型",下意识会想到:

  • 打开文件
  • 保存文件
  • 解析内容

于是代码很快就会变成这样:

ts 复制代码
class FileService {
  load(path: string): string
  save(path: string, content: string)
}

然后页面里这样用:

ts 复制代码
onPageLoad(path) {
  this.content = FileService.load(path)
}

onPageDestroy() {
  FileService.save(path, this.content)
}

表面上看,你"有文件了",但这里其实还没有文档模型

因为:

文件只是存储介质,

文档是运行时对象。

文档模型解决的不是"存不存",而是"活多久"

在 PC 应用里,真正麻烦的问题往往是这些:

  • 什么时候该保存?
  • 多个窗口是不是同一份内容?
  • 页面销毁了,状态还在不在?
  • 程序崩溃前,哪些改动是"已确认"的?

这些问题,文件 API 本身一个都解决不了

所以文档模型的第一件事,不是 IO,而是:

明确谁拥有状态,以及状态的生命周期。

最小可用的文档模型,长什么样

一个合理的起点,其实非常克制:

ts 复制代码
class Document {
  id: string
  content: string
  dirty: boolean

  applyChange(change) {
    this.content = apply(this.content, change)
    this.dirty = true
  }

  markSaved() {
    this.dirty = false
  }
}

注意这里的几个点:

  • 文档是内存对象
  • 状态集中在一个地方
  • 是否需要保存,是文档自己的判断

页面不再持有核心状态:

ts 复制代码
class EditorPage {
  doc: Document

  onLoad(docId) {
    this.doc = DocumentManager.open(docId)
  }

  onInput(change) {
    this.doc.applyChange(change)
  }
}

这一刻开始,页面只是文档的使用者

文档管理器,是比页面更重要的中枢

一旦有多个文档、多窗口,你一定会需要一个统一入口:

ts 复制代码
class DocumentManager {
  docs = new Map<string, Document>()

  open(id) {
    if (!this.docs.has(id)) {
      this.docs.set(id, loadDocument(id))
    }
    return this.docs.get(id)
  }

  close(id) {
    const doc = this.docs.get(id)
    if (doc && doc.dirty) {
      save(doc)
    }
    this.docs.delete(id)
  }
}

这一步非常关键,因为它意味着:

文档的生死,不再由页面决定。

页面只是 attach / detach:

ts 复制代码
onPageDestroy() {
  DocumentManager.detach(this.doc.id)
}

什么时候真正 close,由文档管理器统一判断。

多窗口问题,其实在这里自然消失了

一旦文档是中心,多窗口几乎不用"设计"。

ts 复制代码
const doc = DocumentManager.open(fileId)

openEditorWindow(doc)
openEditorWindow(doc)

两个窗口:

  • 看到的是同一份 content
  • 操作的是同一份状态
  • 保存策略一致

你不需要:

  • 复制状态
  • 手动同步
  • 写额外的桥接逻辑

因为模型本身已经对齐了 PC 使用方式

页面要做的事情,反而变少了

在文档模型下,页面职责会被强制压缩:

ts 复制代码
class EditorPage {
  render(doc) {
    draw(doc.content)
  }

  onUserInput(event) {
    this.doc.applyChange(parse(event))
  }
}

页面不再负责:

  • 状态持久化
  • 生命周期判断
  • 资源回收策略

这不是"页面被削弱",而是职责终于对了

为什么一定要"先"做文档模型

很多项目会想:

先把功能写出来,

后面再抽文档模型。

现实通常是:

  • 状态已经散落在页面里
  • 生命周期假设已经固化
  • 多窗口是补丁
  • 保存逻辑全是特判

这时候再引入文档模型,往往意味着一次大规模重构。

所以在 PC 场景下,正确的顺序应该是:

先定义文档如何存在,
再决定页面如何展示。

一个简单的自检点

如果你现在开始写 HarmonyOS PC 应用,可以问自己一句话:

页面关了,我的数据还应该在吗?

如果答案是"应该在",那这个数据就不该属于页面

总结

在 HarmonyOS PC 应用里,

文档模型不是高级设计,

而是基础设施

它解决的不是"写得优不优雅",而是:

  • 状态是否集中
  • 生命周期是否清晰
  • 多窗口是否天然成立
  • 长时间运行是否安全

当你一开始就把文档模型立住,后面的页面设计、窗口管理、状态同步,都会顺着来。

相关推荐
xym15 小时前
Taskpool简单使用2
harmonyos
不爱吃糖的程序媛16 小时前
鸿蒙 Flutter 多引擎场景开发指导
flutter·华为·harmonyos
小雨青年17 小时前
鸿蒙 HarmonyOS 6 | 多媒体(05)全局播控 AVSession 接入与后台控制
华为·harmonyos
Keya17 小时前
鸿蒙平台实现高斯模糊的渐变色
harmonyos
SuperEugene17 小时前
Vue3 中后台实战:VXE Table 从基础表格到复杂业务表格全攻略 | Vue生态精选篇
前端·vue.js·状态模式·vue3·vxetable
前端不太难18 小时前
OpenClaw 代码里最值得学习的 10 个设计
学习·状态模式
大雷神18 小时前
HarmonyOS APP<玩转React>开源教程四:状态管理基础
react.js·开源·harmonyos
前端不太难19 小时前
90% 的鸿蒙 App,没有真正的依赖管理
华为·状态模式·harmonyos
常利兵19 小时前
Spring Boot接口版本控制:解锁API优雅升级姿势
spring boot·后端·状态模式
江湖有缘20 小时前
基于华为openEuler系统部署MicroBin粘贴板工具
华为·docker·华为云·openeuler