那 HarmonyOS PC 应用到底该怎么落代码?
本文针对HarmonyOS PC应用开发提出关键思维转变:从"页面思维"转向"文档思维"。作者指出PC应用的核心在于文档而非页面,强调文档应独立于窗口存在,由统一管理器控制生命周期。正确做法包括:文档需具备稳定身份和变更通知机制、窗口仅引用文档而非创建、文档生命周期与窗口解耦、多窗口共享同一文档实例自动同步。这种架构能充分利用HarmonyOS PC的多窗口


大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向:前端 / 跨端 / 小程序 / 移动端工程化
内容平台:掘金、知乎、CSDN、简书
创作特点:实战导向、源码拆解、少空谈多落地
文章状态:长期稳定更新,大量原创输出
我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学“明白”,也用“到位”
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
引言
当你开始认真做 HarmonyOS PC 应用,很快会遇到一个绕不开的问题:
理念我懂了,
但代码到底该怎么写?
多窗口、长生命周期、进程常驻、文档并存——这些概念每一个都很“对”,但真正下手时,很多项目还是会不自觉地回到老路:
- 页面里 load 数据
- 页面关闭时 save
- 每个窗口一套状态
- 多窗口靠事件同步
结果就是:代码能跑,但结构已经开始崩。
问题并不在 HarmonyOS,而在于——你还在用 “页面思维” 写 PC 应用。
第一件必须做的事:把“文档”提到页面之上
在 App 里,页面几乎就是一切。但在 PC 应用里,页面只是视图,文档才是主体。
如果你的文档还只是一个 String 或 Model,藏在页面里,那你已经输了。
一个最小但正确的文档定义,应该像这样:
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 上,
页面只是壳,窗口只是入口,
文档,才是应用真正活着的东西。
更多推荐



所有评论(0)