【HarmonyOS Next】鸿蒙中自定义弹框 OpenCustomDialog、CustomDialog 与 DialogHub 的区别详解
前言
在 HarmonyOS NEXT 开发过程中,弹框(Dialog) 几乎是每个应用都会使用到的组件。
例如:
- 登录确认
- 删除确认
- 支付密码
- 分享面板
- Loading
- Toast
- BottomSheet
- 自定义输入框
- 图片预览
- 权限申请
很多刚开始学习 HarmonyOS 的开发者都会有这样的疑问:
HarmonyOS 里面为什么有这么多 Dialog?
官方文档中常见的就有:
- OpenCustomDialog
- CustomDialog
- DialogController
- PromptAction
- AlertDialog
- ActionSheet
- DialogHub(项目封装)
- OverlayManager(API13+)
尤其很多项目里面都会封装一个 DialogHub。
于是很多人会问:
DialogHub 是官方的吗?
不是。
它只是很多大型项目都会封装出来的一个统一管理 Dialog 的方案。
本文将彻底讲清楚:
- OpenCustomDialog 到底是什么?
- CustomDialog 和 OpenCustomDialog 的关系
- DialogController 的作用
- DialogHub 为什么会出现
- 三者适合什么场景
- 企业项目一般如何封装
- 如何避免 Dialog 泄漏
- 如何实现全局弹框
- 如何实现 Promise 风格 Dialog
- 如何实现 Dialog 队列
- 如何实现 Dialog 防重复
本文预计 2 万字左右,建议收藏。
一、HarmonyOS Dialog 发展过程
ArkUI 的 Dialog 大致经历几个阶段。
AlertDialog
│
▼
CustomDialog
│
▼
DialogController
│
▼
OpenCustomDialog
│
▼
OverlayManager(API13)
其中企业开发里面又衍生出了:
DialogHub
注意:
DialogHub 并不是官方组件,而是开发者封装出来的一套管理方案。
二、什么是 OpenCustomDialog
OpenCustomDialog 是 HarmonyOS 提供的:
任意时刻打开一个自定义 Dialog 的能力。
以前使用 Dialog,一般需要:
Button
↓
Controller.open()
必须有 Controller。
现在可以:
Button
↓
openCustomDialog()
直接打开。
例如:
Button("打开Dialog")
.onClick(()=>{
openCustomDialog({
builder: () => {
MyDialog()
}
})
})
是不是简单很多?
它最大的特点
无需 Controller。
无需提前创建对象。
直接打开即可。
所以它非常适合:
- 临时 Dialog
- Toast
- Loading
- 分享面板
- 输入框
三、OpenCustomDialog 原理
内部其实就是:
UIContext
│
▼
Overlay
│
▼
Dialog
流程如下:
点击按钮
│
▼
openCustomDialog()
│
▼
创建Overlay节点
│
▼
插入Window
│
▼
显示Dialog
因此它其实也是 Overlay 的一种。
四、什么是 CustomDialog
CustomDialog 更早。
它本质就是:
一个可以继承的 Dialog 类
例如:
@CustomDialog
struct DeleteDialog{
controller?: CustomDialogController
build(){
Column(){
Text("确定删除吗")
Button("确定")
}
}
}
然后:
let controller=new CustomDialogController({
builder:DeleteDialog()
})
controller.open()
是不是发现:
需要 Controller。
五、为什么需要 Controller
Controller 管理的是:
Dialog 生命周期
包括:
open()
close()
update()
cancel()
例如:
Dialog
│
▼
Controller
│
▼
业务代码
因此 Controller 非常适合:
- 长生命周期
- 多次打开
- 多次关闭
例如:
支付密码。
六、OpenCustomDialog 与 CustomDialog 的区别
| 对比项 | OpenCustomDialog | CustomDialog |
|---|---|---|
| Controller | 不需要 | 需要 |
| 生命周期 | 临时 | 长生命周期 |
| 使用难度 | 简单 | 略复杂 |
| 推荐程度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| 企业使用 | 非常多 | 较多 |
| API 风格 | 函数 | 类 |
| 可复用 | 一般 | 很强 |
| 维护成本 | 低 | 中 |
一句话总结:
OpenCustomDialog 更适合快速弹框;CustomDialog 更适合需要完整生命周期管理和复用的复杂弹框。
七、什么是 DialogHub
重点来了。
很多人第一次看到:
DialogHub.show()
还以为官方 API。
其实:
不是。
它只是:
项目封装
例如:
DialogHub
├── showLoading()
├── hideLoading()
├── showDialog()
├── showConfirm()
├── showSuccess()
├── showError()
├── showInput()
└── showBottomDialog()
是不是很像:
Android:
DialogManager
或者:
iOS:
HUDManager
八、为什么需要 DialogHub
大型项目里面:
假设有:
100
页面
如果每个页面:
new Controller
管理起来会非常混乱。
例如:
PageA
PageB
PageC
PageD
PageE
每个页面:
Loading
Confirm
Input
Toast
Error
Success
可能:
600+
Dialog
维护非常困难。
于是:
统一管理。
DialogHub
│
▼
所有Dialog
九、DialogHub 的核心思想
统一入口。
例如:
DialogHub.showConfirm({
title:"删除",
message:"确定删除吗?"
})
而不是:
new Controller()
controller.open()
业务层根本不用关心 Controller。
十、DialogHub 内部实现思路
一般都会维护:
Map
例如:
Map<String,DialogController>
打开:
不存在
↓
创建
↓
缓存
关闭:
获取Controller
↓
close()
↓
删除
这样整个项目:
只有:
一个
DialogHub
十一、三者关系图
Dialog
│
┌─────────────┴──────────────┐
▼ ▼
CustomDialog OpenCustomDialog
│
▼
DialogController
│
▼
DialogHub(项目封装)
需要注意的是,DialogHub 并不是官方 API,而是建立在官方 Dialog 能力之上的统一管理层。
十二、三者优缺点总结
| 方案 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|
| OpenCustomDialog | 简洁、无需 Controller、开发效率高 | 生命周期控制较弱 | 临时提示、确认框、Loading |
| CustomDialog | 生命周期完整、复用性强 | 代码量较多 | 复杂业务弹框 |
| DialogHub | 统一管理、便于维护、支持扩展 | 需要自行设计与维护 | 中大型项目、团队协作 |
十三、企业级最佳实践
在实际项目中,可以按照以下原则选择:
- 简单页面弹框:优先使用
OpenCustomDialog。 - 复杂、可复用的业务弹框:使用
CustomDialog + DialogController。 - 中大型项目:封装
DialogHub,统一管理 Loading、确认框、输入框、全局提示等能力。 - 需要跨页面、全局展示的浮层:根据 API 版本,优先考虑
OverlayManager等更现代的浮层管理能力。
一个典型的企业架构如下:
业务页面
│
▼
DialogHub
│
├── OpenCustomDialog(简单弹框)
├── CustomDialog(复杂弹框)
└── OverlayManager(全局浮层,API13+)
十四、常见问题(FAQ)
Q1:OpenCustomDialog 会取代 CustomDialog 吗?
不会。
两者定位不同。前者强调快速打开,后者强调生命周期管理与复用。
Q2:DialogHub 是官方提供的吗?
不是。它是很多团队根据项目需求封装的统一 Dialog 管理器,没有官方统一实现。
Q3:什么时候一定要使用 DialogController?
当弹框需要被多次打开、关闭、更新,或者需要在不同逻辑中精确控制生命周期时,DialogController 会更加合适。
Q4:DialogHub 一定要用吗?
小型项目没有必要。随着页面和弹框数量增加,统一管理能够降低维护成本,因此中大型项目更值得采用。
总结
OpenCustomDialog、CustomDialog 和 DialogHub 并不是相互替代的关系,而是分别解决不同层级的问题:
- OpenCustomDialog:官方提供的轻量级弹框能力,适合快速展示临时 Dialog。
- CustomDialog:官方提供的可复用自定义弹框机制,配合
DialogController实现完整生命周期管理。 - DialogHub:项目层面的封装方案,将各种官方 Dialog 能力统一管理,便于大型项目维护和扩展。
如果按企业开发经验给出建议,可以遵循下面这套原则:
| 项目规模 | 推荐方案 |
|---|---|
| 学习 Demo | OpenCustomDialog |
| 中小型项目 | OpenCustomDialog + 少量 CustomDialog |
| 中大型项目 | DialogHub + OpenCustomDialog + CustomDialog |
| 企业级应用 | DialogHub + OverlayManager(新版 API)+ 自定义弹框组件体系 |
掌握这三者的定位和协作方式,可以帮助你设计出更清晰、更易维护的鸿蒙弹框架构,也能避免后期因为弹框管理混乱而带来的维护成本。
更多推荐

所有评论(0)