在这里插入图片描述
在这里插入图片描述

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

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

我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。

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

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

子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学“明白”,也用“到位”

持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱

引言

当你开始认真做 HarmonyOS PC 应用,很快会遇到一个绕不开的问题:

理念我懂了,
但代码到底该怎么写?

多窗口、长生命周期、进程常驻、文档并存——这些概念每一个都很“对”,但真正下手时,很多项目还是会不自觉地回到老路:

  • 页面里 load 数据
  • 页面关闭时 save
  • 每个窗口一套状态
  • 多窗口靠事件同步

结果就是:代码能跑,但结构已经开始崩。

问题并不在 HarmonyOS,而在于——你还在用 “页面思维” 写 PC 应用。

第一件必须做的事:把“文档”提到页面之上

在 App 里,页面几乎就是一切。但在 PC 应用里,页面只是视图,文档才是主体。

如果你的文档还只是一个 StringModel,藏在页面里,那你已经输了。

一个最小但正确的文档定义,应该像这样:

export class Document {
  readonly id: string
  private _content: string
  private _version = 0

  constructor(id: string, content: string) {
    this.id = id
    this._content = content
  }

  get content() {
    return this._content
  }

  update(next: string) {
    this._content = next
    this._version++
    this.notify()
  }

  onChange(cb: () => void) {
    // 订阅变更
  }

  private notify() {}
}

注意几个关键点:

  • 文档有稳定的 身份
  • 状态只允许通过方法修改
  • 页面不能直接控制字段

这一步的本质是:

切断页面对核心状态的控制权。

第二件事:窗口不创建文档,只“获取”文档

这是从页面思维切换过来时,最容易犯的错误

错误写法

@Entry
@Component
struct EditorWindow {
  @State doc = new Document("a.txt", load("a.txt"))
}

问题只有一个,但是致命的:

每个窗口一份文档实例。

多窗口一开,数据立刻分叉。

正确方式:文档由管理器统一提供

class DocumentManager {
  private docs = new Map<string, Document>()

  open(id: string): Document {
    if (!this.docs.has(id)) {
      this.docs.set(id, new Document(id, load(id)))
    }
    return this.docs.get(id)!
  }
}

窗口里只做一件事:

@Entry
@Component
struct EditorWindow {
  doc: Document = docManager.open("a.txt")

  build() {
    EditorView({ doc: this.doc })
  }
}

一句话总结:

窗口只能“使用文档”,不能“拥有文档”。

第三件事:窗口生命周期 ≠ 文档生命周期

这是 PC 应用和移动 App 最本质的分界线。
在 HarmonyOS PC 上:

  • 窗口可以随时关闭
  • 应用进程可能继续存在
  • 文档可能被多个窗口同时引用

所以这类代码,本质上是错的:

aboutToDisappear() {
  save(this.doc)
}

正确的释放逻辑,只能存在于文档层

class DocumentManager {
  private refs = new Map<string, number>()

  acquire(id: string): Document {
    this.refs.set(id, (this.refs.get(id) ?? 0) + 1)
    return this.open(id)
  }

  release(id: string) {
    const count = (this.refs.get(id) ?? 1) - 1
    if (count === 0) {
      this.saveAndDispose(id)
    } else {
      this.refs.set(id, count)
    }
  }
}

窗口关闭时,只通知:

onWindowClose() {
  docManager.release(this.doc.id)
}

这一步意味着:

保存行为,从页面钩子,升级为系统级策略。

多窗口同步,其实不需要“通信”

很多人一提多窗口,第一反应是:

怎么同步?
怎么发事件?

但在文档模型下,这个问题根本不存在。

doc.onChange(() => {
  this.render()
})

因为:

  • 所有窗口拿的是同一个 Document
  • 状态天然一致
  • 不存在“同步”的概念

你不是在同步数据,你只是在重新渲染同一个事实

保存,不再是行为,而是策略

页面思维下,常见纠结是:

  • 什么时候保存?
  • 切后台要不要保存?
  • 关闭窗口算不算一次保存?

文档思维下,这些问题直接换了一个维度:

class SavePolicy {
  autoSaveInterval = 3s
  saveOnAllWindowsClosed = true
}

页面对此一无所知。它只负责展示和编辑,不负责“人生大事”。

HarmonyOS PC 为什么“逼你”这样写?

因为它天然支持:

  • 多窗口
  • 多实例
  • 长生命周期进程

如果你还用页面思维:

系统能力越强,
你的结构越容易崩。

一个判断你是否写对了的标准

如果你的项目已经满足:

  • 页面里不再 load / save
  • 窗口关闭不影响文档存在
  • 多窗口不需要互相通信
  • 文档可以被多个视图同时引用

那基本可以确认一件事:

你已经在写真正的 PC 应用了。

总结

在 HarmonyOS PC 上,
页面只是壳,窗口只是入口,
文档,才是应用真正活着的东西。

Logo

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

更多推荐