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

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

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

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

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

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

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

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

引言

如果你第一次做 HarmonyOS PC 应用,大概率会有一种感觉:

“这不就是 App,
屏幕更大、窗口更多一点吗?”

于是你会很自然地:

  • 复用 App 的页面结构
  • 复用 App 的状态模型
  • 复用 App 的生命周期理解

短期内,这些选择都能跑。但只要项目一复杂,你就会开始发现:

问题不是“适不适配大屏”,
而是整个模型就不对。

一个最典型的“放大版 App”写法

很多 PC 项目,一开始都长这样:

@Entry
@Component
struct MainPage {
  @State currentPage: string = 'home'

  build() {
    if (this.currentPage === 'home') {
      HomeView()
    } else if (this.currentPage === 'editor') {
      EditorView()
    }
  }
}

这是非常标准的 App 思维:

  • 单入口
  • 单状态
  • 页面切换即状态切换

在移动端,这没问题。

但一旦放到 PC 环境,你马上会遇到第一个现实需求。

PC 世界的第一刀:多窗口

PC 用户不会问你:

“能不能返回?”

他们会问:

“能不能再开一个?”

于是你开始加代码:

@State windows: WindowInfo[] = []

openWindow(type) {
  this.windows.push(createWindow(type))
}

接着你发现问题来了:

  • currentPage 失去意义
  • 状态开始分叉
  • 页面不再是“线性路径”

App 的“页面栈”模型,第一次失效。

App 的状态模型,在 PC 下会迅速膨胀

为了支撑多窗口,你会开始写这种状态:

interface WindowState {
  id: string
  active: boolean
  doc?: Document
}

@State windowStates: WindowState[] = []

然后逻辑开始变得复杂:

activateWindow(id) {
  this.windowStates.forEach(w => w.active = false)
  find(id).active = true
}

你慢慢会意识到一件事:

你已经不在写“页面状态”,
而是在写“进程级状态”。

但你还在用 App 的方式管理它。

PC 应用的核心,不是页面,而是“对象生命周期”

在 PC 应用里,真正长期存在的往往是这些东西:

  • 文档
  • 会话
  • 编辑上下文
  • 后台任务
  • 文件句柄

比如一个编辑器型应用,核心代码更像这样:

class DocumentSession {
  path: string
  dirty: boolean
  cursor: Position
}

这些对象的特点是:

  • 生命周期可能是小时级
  • 独立于任何窗口存在
  • 可以被多个窗口引用

这和 App 的页面状态,几乎是两个世界。

如果你还用 App 的生命周期,会发生什么?

很多团队会继续用 App 的方式思考:

onBackground() {
  saveAll()
}

onForeground() {
  restoreAll()
}

但 PC 应用更关心的是:

  • 窗口是否最小化
  • 是否仍在运行
  • 是否在后台计算
  • 是否有未保存内容

换句话说:

PC 应用的“活着”,
和是否在前台几乎无关。

一个更接近 PC 思维的结构

成熟的 HarmonyOS PC 应用,更像是这样分层:

App Shell
 ├─ 生命周期
 ├─ 系统集成
 └─ 菜单 / 快捷键

Application Core
 ├─ Document / Session
 ├─ Task Manager
 ├─ Undo / Redo
 └─ State Persistence

Window Layer
 ├─ WindowController
 ├─ View Binding
 └─ Focus / Input

关键点在于:

窗口只是视图,
状态不属于它。

用代码对比,差异会非常明显

错误的 App 化写法

@Component
struct EditorPage {
  @State doc: Document
}

文档跟着页面走,页面销毁,文档就危险了。

更合理的 PC 写法

class DocumentManager {
  open(path): DocumentSession
  close(session)
}
@Component
struct EditorWindow {
  session: DocumentSession
}

窗口只是“绑定”文档,而不是“拥有”文档。

输入模型:PC 和 App 根本不是一回事

App 更关注:

  • 触摸
  • 手势
  • 页面级响应

PC 应用的核心是:

  • 键盘
  • 鼠标
  • 焦点
  • 快捷键冲突

这意味着:

onKeyDown(event) {
  if (event.ctrl && event.key === 'S') {
    save()
  }
}

这类逻辑,不应该挂在某个页面上,而应该挂在应用核心或窗口控制器里。

“放大版 App”为什么一定会失控?

因为它默认:

  • 页面 = 世界
  • 页面切换 = 状态切换
  • 生命周期 = 进程生命周期

而 PC 应用真实的世界是:

  • 对象长期存在
  • 多窗口并行
  • 后台持续运行

这不是尺寸问题,是模型问题

总结

如果你问:

HarmonyOS PC 应用,真的只是“放大版 App”吗?

答案其实很简单:

UI 可以放大,
但模型不能。

HarmonyOS 给了你:

  • 同一套语言
  • 同一套 UI 框架
  • 同一套系统能力

但它并没有承诺:

你可以用同一套应用模型,
覆盖所有形态。

真正跑得久的 PC 应用,都会在某一刻意识到:

页面只是入口,
对象和生命周期才是核心。

Logo

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

更多推荐