当前位置: 首页 > news >正文

HarmonyOS PC 文档模型完整范式


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

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

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

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

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

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

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

文章目录

    • 引言
    • 一、先划清三层:不要一开始就写 UI
    • 二、文档模型:不是数据,而是“状态载体”
      • 错误理解:文档 = 一段内容
      • 正确做法:文档是一个“运行态对象”
    • 三、Workspace:PC 世界的真正核心
      • Workspace 管什么?
      • 一个最小可用的 Workspace 模型
    • 四、Controller:把“操作流程”从 UI 中拔出来
      • 错误:UI 直接 orchestrate 一切
      • 正确:引入 WorkspaceController
    • 五、UI:只是“视图 + 事件映射”
    • 六、为什么这套模型特别适合 PC?
    • 七、一个现实世界的对照
    • 总结

引言

PC 形态下,页面不是核心,文档才是。

那接下来真正的问题只有一个:

文档模型,到底该怎么设计,才能撑住多窗口、状态一致性和长期演进?

一、先划清三层:不要一开始就写 UI

一个标准的 HarmonyOS PC 文档模型,至少拆成三层:

┌──────────────────┐ │ UI(窗口 / 页面) │ └────────▲─────────┘ │ 订阅 ┌────────┴─────────┐ │ 形态模型层 │ ← PC 专属 │ Workspace / Doc │ └────────▲─────────┘ │ 调用 ┌────────┴─────────┐ │ 共用能力层 │ │ Repository / IO │ └──────────────────┘

注意顺序:

  • UI 最后写
  • 模型先稳定
  • 能力层完全不关心形态

二、文档模型:不是数据,而是“状态载体”

错误理解:文档 = 一段内容

interfaceDocument{id:stringcontent:string}

这只能算存储结构,不算模型。

正确做法:文档是一个“运行态对象”

// pc/model/DocumentModel.tsexportclassDocumentModel{readonlyid:stringcontent:stringisDirty:boolean=falselastFocusedAt:number=Date.now()constructor(doc:Document){this.id=doc.idthis.content=doc.content}updateContent(newContent:string){this.content=newContentthis.isDirty=true}}

这里开始出现关键差异:

  • 文档有生命周期
  • 文档知道自己“是否被修改”
  • UI 不再自己维护脏状态

三、Workspace:PC 世界的真正核心

如果只记住一句话,那就是:

PC 应用里,Workspace 才是根对象。

Workspace 管什么?

  • 当前打开了哪些文档
  • 文档之间的关系
  • 应用级行为(保存、关闭、恢复)

一个最小可用的 Workspace 模型

// pc/model/WorkspaceModel.tsexportclassWorkspaceModel{privatedocuments=newMap<string,DocumentModel>()open(doc:Document){if(!this.documents.has(doc.id)){this.documents.set(doc.id,newDocumentModel(doc))}}close(docId:string){this.documents.delete(docId)}list():DocumentModel[]{return[...this.documents.values()]}hasDirtyDocument():boolean{returnthis.list().some(d=>d.isDirty)}}

这里有一个非常重要的工程价值

Workspace 是唯一知道“当前应用状态”的地方。

UI 不需要猜,Service 不需要猜。

四、Controller:把“操作流程”从 UI 中拔出来

错误:UI 直接 orchestrate 一切

onCloseApp(){if(doc.isDirty){save()}exit()}

这种代码一旦出现:

  • 自动保存
  • 批量关闭
  • 崩溃恢复

全都没法统一。

正确:引入 WorkspaceController

// pc/controller/WorkspaceController.tsexportclassWorkspaceController{constructor(privateworkspace:WorkspaceModel,privaterepo:DocumentRepository){}saveAll(){for(constdocofthis.workspace.list()){if(doc.isDirty){this.repo.save({id:doc.id,content:doc.content})doc.isDirty=false}}}canExit():boolean{return!this.workspace.hasDirtyDocument()}}

现在:

  • UI 只发意图
  • Controller 统一流程
  • 模型是状态来源

五、UI:只是“视图 + 事件映射”

到这一步,UI 会变得异常干净。

// EditorWindow.ets@StatedocModel!:DocumentModelbuild(){TextArea({text:this.docModel.content}).onChange(v=>this.docModel.updateContent(v))}

你会发现:

  • UI 不保存任何业务状态
  • 没有保存逻辑
  • 没有生命周期判断

UI 只是模型的一个投影。

六、为什么这套模型特别适合 PC?

因为它天然支持:

  • 多窗口
  • 多文档
  • 后台保存
  • 崩溃恢复
  • 文档级权限控制

而且每一个能力都有清晰落点

能力归属
是否修改DocumentModel
当前打开文档Workspace
保存策略Controller
展示UI

七、一个现实世界的对照

如果你做过这些产品:

  • VS Code
  • Photoshop
  • Keynote
  • Xcode

你会发现它们无一不是文档模型驱动。HarmonyOS PC 只是终于走到了同一个阶段。

总结

HarmonyOS PC 应用的复杂度,不来自窗口多,而来自你有没有一个能承载复杂度的模型。

  • 没有文档模型 → 状态迟早进 UI
  • 没有 Workspace → 多窗口一定崩
  • 没有 Controller → 行为一定散
http://www.jsqmd.com/news/331558/

相关文章:

  • 华府便利店信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
  • HarmonyOS 项目中如何拆分共用层与形态模型
  • 大语言模型综合排行榜 26-02-01图片本周排名前10的模型为:Gemini 3 ProGPT-5.2Gemini 3 FlashClaude Opus 4.5GPT
  • Qwen3-Coder: 在世界中自主编程
  • 为什么 MES 集成项目会普遍采用“点对点”的集成模式
  • 2026-02-02 全国各地响应最快的 BT Tracker 服务器(移动版)
  • UE5 多线程(2-3):时间范围类 FDateRange 与 TRange<T>。
  • Linux基础指令(一)
  • 不是所有AI爆款都靠运气,Clawbot作者之一Peter Steinberger,已经为开源社区写了10多年的贡献
  • Nano-Banana保姆级教学:white background+flat lay提示词组合技巧
  • WAN2.2-文生视频+SDXL_Prompt风格实战案例:独立开发者打造AI短视频SaaS原型
  • 轻量级模型实测:YOLOv13-N仅2.5M参数高效运行
  • 深入探讨Clang 16的Niebloid编译问题
  • RTX 4090优化神器:Anything to RealCharacters 2.5D转真人实战体验
  • DeepSeek-OCR-2惊艳案例:手写签名+印刷正文混合文档,仅正文结构化输出
  • 巴菲特-芒格的氢能源投资:清洁能源的下一个前沿
  • 深入解析:在Exchange Online PowerShell中排序邮箱文件夹权限
  • Qwen-Image-Lightning极速文生图:4步生成高清大图保姆级教程
  • 深入探讨 .ConfigureAwait() 的实际用途
  • Qwen2.5-1.5B开源镜像教程:torch.no_grad显存优化+temperature/top_p参数调优
  • EagleEye作品展示:支持多边形ROI区域设定,仅检测指定兴趣区内的目标
  • 解决C++库冲突:raylib与cURL并用
  • AI应用架构师视角:经济学多智能体系统的目标函数设计
  • 开源MinerU镜像免配置实操:3步完成学术论文图像解析与多轮对话
  • 深入理解二因素方差分析中的匹配对比
  • 从XML到JSON的转换与解析
  • 零基础也能用!万物识别-中文-通用领域镜像保姆级入门教程
  • Lychee多模态重排序模型在电商搜索中的惊艳效果展示
  • 函数调用的艺术:如何优雅地组合函数
  • YOLOv13镜像真实案例:产线微小缺陷检测成功