大家好,我是子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向:前端 / 跨端 / 小程序 / 移动端工程化
内容平台:掘金、知乎、CSDN、简书
创作特点:实战导向、源码拆解、少空谈多落地
文章状态:长期稳定更新,大量原创输出
我的内容主要围绕前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读展开。文章不会停留在“API 怎么用”,而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取11 类前端进阶学习资源(工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学“明白”,也用“到位”
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
- 引言
- 第一件必须做的事:把“文档”提到页面之上
- 第二件事:窗口不创建文档,只“获取”文档
- 错误写法
- 正确方式:文档由管理器统一提供
- 第三件事:窗口生命周期 ≠ 文档生命周期
- 正确的释放逻辑,只能存在于文档层
- 多窗口同步,其实不需要“通信”
- 保存,不再是行为,而是策略
- HarmonyOS PC 为什么“逼你”这样写?
- 一个判断你是否写对了的标准
- 总结
引言
当你开始认真做 HarmonyOS PC 应用,很快会遇到一个绕不开的问题:
理念我懂了,
但代码到底该怎么写?
多窗口、长生命周期、进程常驻、文档并存——这些概念每一个都很“对”,但真正下手时,很多项目还是会不自觉地回到老路:
- 页面里 load 数据
- 页面关闭时 save
- 每个窗口一套状态
- 多窗口靠事件同步
结果就是:代码能跑,但结构已经开始崩。
问题并不在 HarmonyOS,而在于——你还在用“页面思维” 写 PC 应用。
第一件必须做的事:把“文档”提到页面之上
在 App 里,页面几乎就是一切。但在 PC 应用里,页面只是视图,文档才是主体。
如果你的文档还只是一个String或Model,藏在页面里,那你已经输了。
一个最小但正确的文档定义,应该像这样:
exportclassDocument{readonlyid:stringprivate_content:stringprivate_version=0constructor(id:string,content:string){this.id=idthis._content=content}getcontent(){returnthis._content}update(next:string){this._content=nextthis._version++this.notify()}onChange(cb:()=>void){// 订阅变更}privatenotify(){}}注意几个关键点:
- 文档有稳定的身份
- 状态只允许通过方法修改
- 页面不能直接控制字段
这一步的本质是:
切断页面对核心状态的控制权。
第二件事:窗口不创建文档,只“获取”文档
这是从页面思维切换过来时,最容易犯的错误。
错误写法
@Entry@Componentstruct EditorWindow{@Statedoc=newDocument("a.txt",load("a.txt"))}问题只有一个,但是致命的:
每个窗口一份文档实例。
多窗口一开,数据立刻分叉。
正确方式:文档由管理器统一提供
classDocumentManager{privatedocs=newMap<string,Document>()open(id:string):Document{if(!this.docs.has(id)){this.docs.set(id,newDocument(id,load(id)))}returnthis.docs.get(id)!}}窗口里只做一件事:
@Entry@Componentstruct EditorWindow{doc:Document=docManager.open("a.txt")build(){EditorView({doc:this.doc})}}一句话总结:
窗口只能“使用文档”,不能“拥有文档”。
第三件事:窗口生命周期 ≠ 文档生命周期
这是 PC 应用和移动 App 最本质的分界线。
在 HarmonyOS PC 上:
- 窗口可以随时关闭
- 应用进程可能继续存在
- 文档可能被多个窗口同时引用
所以这类代码,本质上是错的:
aboutToDisappear(){save(this.doc)}正确的释放逻辑,只能存在于文档层
classDocumentManager{privaterefs=newMap<string,number>()acquire(id:string):Document{this.refs.set(id,(this.refs.get(id)??0)+1)returnthis.open(id)}release(id:string){constcount=(this.refs.get(id)??1)-1if(count===0){this.saveAndDispose(id)}else{this.refs.set(id,count)}}}窗口关闭时,只通知:
onWindowClose(){docManager.release(this.doc.id)}这一步意味着:
保存行为,从页面钩子,升级为系统级策略。
多窗口同步,其实不需要“通信”
很多人一提多窗口,第一反应是:
怎么同步?
怎么发事件?
但在文档模型下,这个问题根本不存在。
doc.onChange(()=>{this.render()})因为:
- 所有窗口拿的是同一个 Document
- 状态天然一致
- 不存在“同步”的概念
你不是在同步数据,你只是在重新渲染同一个事实。
保存,不再是行为,而是策略
页面思维下,常见纠结是:
- 什么时候保存?
- 切后台要不要保存?
- 关闭窗口算不算一次保存?
文档思维下,这些问题直接换了一个维度:
classSavePolicy{autoSaveInterval=3s saveOnAllWindowsClosed=true}页面对此一无所知。它只负责展示和编辑,不负责“人生大事”。
HarmonyOS PC 为什么“逼你”这样写?
因为它天然支持:
- 多窗口
- 多实例
- 长生命周期进程
如果你还用页面思维:
系统能力越强,
你的结构越容易崩。
一个判断你是否写对了的标准
如果你的项目已经满足:
- 页面里不再 load / save
- 窗口关闭不影响文档存在
- 多窗口不需要互相通信
- 文档可以被多个视图同时引用
那基本可以确认一件事:
你已经在写真正的 PC 应用了。
总结
在 HarmonyOS PC 上,
页面只是壳,窗口只是入口,
文档,才是应用真正活着的东西。