一、引言

时间是移动端应用中最基础的信息维度之一。从锁屏界面的时钟到闹钟 App 的倒计时,从日历的日期显示到世界时钟的时区转换——时间的展示无处不在。在传统开发中,要实现一个实时更新的数字时钟,开发者需要创建定时器、获取系统时间、格式化字符串、每秒刷新——即使是最简单的"显示当前时间"也需要十几行代码。

HarmonyOS NEXT 在 API 10 中推出了 TextClock 组件——一个自动获取系统时间并实时更新的文本组件。开发者只需声明时间格式和样式,TextClock 就会自动渲染当前时间并每秒刷新,无需手动管理定时器,无需手动获取系统时间。

本文通过一个数字时钟展廊 Demo 深入讲解 TextClock 组件的核心用法:如何定义时间格式?12/24 小时制如何切换?如何组合多种格式展示?以及 TextClock 与普通 Text 的本质区别。

阅读完本文,你将能够:

  • 使用 TextClock 替代手动的定时器+格式化的时间展示方案
  • 掌握 format 方法的时间格式字符串
  • 实现 12/24 小时制的动态切换
  • 组合多个 TextClock 实例展示不同格式的时间
  • 理解 TextClock 的自动刷新机制和适用场景

二、TextClock 组件 API 总览

2.1 构造函数

TextClock()

TextClock 的构造函数不接受任何参数——所有配置通过链式方法完成。这与其他 ArkUI 组件(如 Rating({ rating: 0 })Toggle({ type: ToggleType.Switch }))不同。

2.2 format(format: string)

设置时间的显示格式,是 TextClock 最核心的方法:

TextClock()
  .format('HH:mm:ss')

格式字符串使用标准的时间格式化占位符:

占位符 含义 示例
yyyy 四位年份 2026
yy 两位年份 26
MM 两位月份 06
dd 两位日期 26
HH 24 小时制小时(00-23) 14
hh 12 小时制小时(01-12) 02
mm 分钟(00-59) 30
ss 秒(00-59) 45
a AM/PM 标记 PM
dddd 星期全名 Friday
ddd 星期缩写 Fri
EEEE 星期全名(中文环境) 星期五
E 星期缩写(中文环境) 周五

常用的格式组合:

格式字符串 显示效果
HH:mm 14:30
HH:mm:ss 14:30:45
hh:mm a 02:30 PM
yyyy-MM-dd 2026-06-26
yyyy-MM-dd HH:mm:ss 2026-06-26 14:30:45
yyyy年MM月dd日 dddd 2026年06月26日 Friday

2.3 通用属性

TextClock 继承了 Text 的所有通用样式属性:

TextClock()
  .format('HH:mm:ss')
  .fontSize(52)           // 字体大小
  .fontColor('#1a1a2e')   // 字体颜色
  .fontWeight(FontWeight.Bold)  // 字重
  .fontFamily('monospace')      // 字体族

使用 monospace(等宽字体)对于时间显示非常重要——如果使用比例字体,数字 1 比 0 窄,每次秒数变化时文字宽度也会变化,导致时钟"抖动"。等宽字体保证了每个数字字符宽度一致,时钟显示稳定。

2.4 TextClock 与 Text 的本质区别

TextClock 虽然继承了 Text 的样式属性,但它与 Text 有根本性的区别:

特性 Text TextClock
内容来源 开发者指定的静态字符串 系统时间(自动获取)
更新方式 手动修改 content 自动每秒刷新
定时器 需要开发者管理 组件内部自动管理
格式化 开发者手动格式化 Date format 方法声明式指定

TextClock 是一个自更新组件——它在挂载后启动内部定时器,每秒读取系统时间、按 format 格式化为字符串、更新渲染。页面销毁时,内部定时器自动清理,无需开发者手动管理。
在这里插入图片描述

三、Demo 设计:数字时钟展廊

3.1 功能概述

Demo 是一个数字时钟展廊,展示 TextClock 的多种格式和交互方式:

  1. 大时钟区:52sp 超大字号的主要时钟,显示当前时间(HH:mm:ss 或 hh:mm:ss a),下方可选显示日期
  2. 格式控制区:三个 Toggle 开关——24 小时制/12 小时制、显示/隐藏秒、显示/隐藏日期
  3. 多格式预览区:三个 TextClock 实例同时展示不同格式——完整日期时间、仅时间、仅日期
  4. 时区信息区:说明 TextClock 的时区参数用法

3.2 动态格式切换

12/24 小时制和秒的显示通过 timeFormat() 方法动态生成格式字符串:

timeFormat(): string {
  if (this.use24Hour) {
    return this.showSeconds ? 'HH:mm:ss' : 'HH:mm';
  } else {
    return this.showSeconds ? 'hh:mm:ss a' : 'hh:mm a';
  }
}

当前状态为 24 小时制 + 显示秒时,格式为 HH:mm:ss,时钟显示为 14:30:45。切换到 12 小时制后,格式变为 hh:mm:ss a,时钟显示为 02:30:45 PM。切换是即时的——因为格式字符串变化后,TextClock 在下一秒刷新时自动应用新格式。

Toggle 开关直接修改 @State use24Hour@State showSeconds,格式方法依赖这些状态变量。格式变化后,所有绑定到同一格式的 TextClock 实例同步切换——不需要遍历组件或手动刷新。

3.3 多格式同时展示

Demo 中有 5 个 TextClock 实例,每个使用不同的格式字符串:

// 主时钟(大字号)
TextClock()
  .format(this.timeFormat())   // HH:mm:ss 或 hh:mm:ss a
  .fontSize(52)

// 日期(条件渲染)
TextClock()
  .format(this.dateFormat())   // yyyy-MM-dd dddd
  .fontSize(16)

// 多格式预览区
TextClock().format(this.fullFormat())  // 完整日期时间
TextClock().format(this.timeFormat())  // 仅时间
TextClock().format('yyyy-MM-dd EEEE')  // 仅日期

多个 TextClock 实例共享同一个系统时间源,因此所有时钟显示的时间完全一致,不会出现"大时钟是 14:30:45,小时钟是 14:30:44"的偏差。这是因为每个 TextClock 在刷新时都直接从系统读取当前时间,而不是依赖上一步的状态累加。

3.4 格式预览区

多格式预览区是一个教学性设计——每行左侧是格式标签(如"完整日期时间"),中间是 TextClock 显示的实时结果,右侧是格式字符串(如 yyyy-MM-dd HH:mm:ss)。三列并排让读者直观理解"格式字符串 → 显示效果"的映射关系。

这种设计对学习 TextClock 的格式字符串非常有帮助——读者可以对照格式字符串和实际输出,理解每个占位符的含义。在实际产品中,你不会同时展示格式字符串,但 Demo 中的这种"格式→结果"对照是教学的最佳方式。

3.5 时区说明

TextClock 支持通过 timeZoneOffset 方法指定时区偏移:

// 未指定时区 → 使用系统时区
TextClock().format('HH:mm:ss')

// 指定 UTC+0(伦敦)
TextClock()
  .format('HH:mm:ss')
  .timeZoneOffset(0)

// 指定 UTC-5(纽约)
TextClock()
  .format('HH:mm:ss')
  .timeZoneOffset(-5)

Demo 中当前使用的是系统默认时区(UTC+8 北京)。时区信息卡片说明了 timeZoneOffset 的用法——在实际项目中,世界时钟功能的每个城市时钟会设置不同的时区偏移。

3.6 页面结构

┌──────────────────────────────────────────┐
│ 🕐 数字时钟(深色标题栏)                  │
├──────────────────────────────────────────┤
│ 📘 TextClock 组件说明卡片                 │
├──────────────────────────────────────────┤
│ ┌────────────────────────────────────┐   │
│ │           14:30:45                  │   │ ← 52sp 大时钟
│ │       2026-06-26 Friday             │   │ ← 日期(可隐藏)
│ └────────────────────────────────────┘   │
├──────────────────────────────────────────┤
│ 格式设置                                  │
│ ┌────────────────────────────────────┐   │
│ │ 24 小时制              [====]      │   │
│ │ 显示秒                  [====]      │   │
│ │ 显示日期                [====]      │   │
│ └────────────────────────────────────┘   │
├──────────────────────────────────────────┤
│ 多格式预览                                │
│ ┌────────────────────────────────────┐   │
│ │ 完整日期时间  2026-06-26 14:30:45  │   │
│ │ 仅时间        14:30:45             │   │
│ │ 仅日期        2026-06-26 Friday    │   │
│ └────────────────────────────────────┘   │
├──────────────────────────────────────────┤
│ 🌍 时区信息                    UTC+8    │
└──────────────────────────────────────────┘

在这里插入图片描述

四、TextClock 组件的最佳实践

4.1 格式字符串设计

格式字符串应根据使用场景选择合适的详细程度:

  • 锁屏/主屏幕时钟HH:mm(简洁,只显示时和分)
  • 秒表/计时器HH:mm:ss(或 mm:ss 用于短计时)
  • 日历/日程yyyy-MM-dd dddd(日期 + 星期)
  • 完整时间戳yyyy-MM-dd HH:mm:ss(日志、数据记录)
  • 12 小时制场景hh:mm a(美国市场,AM/PM 区分上午下午)
  • 中文语境yyyy年MM月dd日 EEEE(更适合国内用户阅读习惯)

格式设计的一个原则:不要显示用户不需要的精度。锁屏不需要秒——它增加了视觉噪音;日历不需要时分秒——它让日期信息淹没在时间细节中。

4.2 等宽字体的重要性

时间显示必须使用等宽字体:

TextClock()
  .format('HH:mm:ss')
  .fontFamily('monospace')

不使用等宽字体的后果:当时间从 11:11:11 变为 11:11:12 时(或更极端的 00:00:08 变为 00:00:09),由于数字 1 比 0、8 窄,整个时钟字符串的宽度会微小变化,导致时钟在视觉上"抖动"。等宽字体消除了这个问题。

4.3 多个 TextClock 实例

如果需要同时展示多个时间格式(如 Demo 中的多格式预览区),创建多个 TextClock 实例而非尝试复用单个实例。TextClock 的设计目标就是"一个实例 = 一个格式 = 一个时间展示"。

多个 TextClock 不共享内部定时器——每个实例维护自己的刷新循环。但对于 5 个以内的实例,性能开销可以忽略(每个实例每秒只执行一次字符串格式化)。

4.4 与定时器的对比

在 TextClock 出现之前,开发者这样实现实时时钟:

// 传统方式(不推荐)
@State currentTime: string = '';
private timer: number = -1;

aboutToAppear(): void {
  this.timer = setInterval(() => {
    const now = new Date();
    this.currentTime = this.formatDate(now, 'HH:mm:ss');
  }, 1000);
}

aboutToDisappear(): void {
  clearInterval(this.timer);
}

TextClock 将这一切封装为声明式组件——不需要 setInterval、不需要 aboutToDisappear 清理、不需要格式化函数。一行声明替代了十几行手动代码。

但 TextClock 的格式选项有限——它只支持标准的时间占位符,不支持自定义逻辑(如"3 分钟前"、"刚刚"等相对时间)。相对时间展示仍然需要使用定时器+自定义格式化。

4.5 性能注意事项

TextClock 每秒自动刷新一次。这意味着一页上有 5 个 TextClock 时,每秒触发 5 次文字更新。对于简单的文字渲染,这个开销微不足道(<1ms)。但如果在 TextClock 的父组件中有复杂的重新计算逻辑,需要注意每秒更新可能触发的连锁渲染。

优化建议:将 TextClock 放在尽可能独立的子组件中,减少父组件的重新渲染范围。

五、完整代码结构

TextClockPage (~200 行)
├── 状态变量
│   ├── @State use24Hour — 24小时制/12小时制
│   ├── @State showSeconds — 显示/隐藏秒
│   └── @State showDate — 显示/隐藏日期
├── 格式方法
│   ├── timeFormat() — 动态生成时间格式字符串
│   ├── dateFormat() — 日期格式字符串
│   └── fullFormat() — 完整日期时间格式字符串
├── 视图
│   ├── 标题栏 — 🕐 数字时钟
│   ├── 说明卡片 — TextClock 组件介绍
│   ├── 大时钟区 — TextClock(52sp) + 日期 TextClock
│   ├── 格式控制区(3 个 Toggle)
│   ├── 多格式预览区(3 个 TextClock 实例)
│   └── 时区信息卡片
└── @Builder formatCard() — 格式预览行(标签 + TextClock + 格式字符串)

六、总结

本文通过一个数字时钟展廊 Demo 深入讲解了 HarmonyOS NEXT 中的 TextClock 文本时钟组件。TextClock 将传统的手动定时器+格式化方案封装为声明式组件,通过 format 方法指定显示格式,自动获取系统时间并每秒刷新。

核心要点回顾:

  1. TextClock 是自更新组件:不需要手动 setInterval、不需要 new Date()、不需要格式化函数。TextClock 在挂载时启动内部定时器,页面销毁时自动清理。这比手动定时器方案更安全(不会忘记清理)且代码量少一个数量级。

  2. format 方法控制显示:格式字符串使用标准的 yyyy/MM/dd/HH/mm/ss/a/dddd 占位符。通过动态修改格式字符串(绑定到 @State),可以在 12/24 小时制之间即时切换。

  3. 等宽字体是必须的:时间显示应使用 fontFamily('monospace'),避免比例字体导致的数字宽度变化和时钟抖动。

  4. 多实例 = 多格式:需要展示多种时间格式时,创建多个 TextClock 实例而非尝试复用。每个实例有独立的格式和样式,但读取同一系统时间源,保证一致性。

  5. TextClock vs Text:Text 显示静态内容,TextClock 显示实时时间。TextClock 继承了 Text 的所有样式属性(fontSize、fontColor、fontWeight 等),但内容来源和更新机制完全不同。

TextClock 是 HarmonyOS NEXT 中"自动化优先"设计哲学的典型代表——开发者不需要管理定时器、不需要处理生命周期、不需要格式化日期,只需声明"显示什么格式的时间",组件自己完成剩下的一切。这种"声明即运行"的模式,大幅降低了实时时间展示的开发成本和时间 Bug 的风险。

七、扩展思考

TextClock 解决了基本的实时时间展示需求,但在实际项目中,时间展示还有更多变化:

世界时钟:结合 timeZoneOffset 参数和多个 TextClock 实例,可以构建世界时钟页面——每个时钟实例设置不同的时区偏移,展示不同城市的时间。格式字符串可以保持一致(如都用 HH:mm),时区差异由 timeZoneOffset 控制。

秒表的局限性:TextClock 始终显示系统时间,无法用于秒表/倒计时等场景——那些需要显示"从某个起点经过的时间"而非"系统当前时间"。秒表仍然需要手动定时器方案。

自定义时间源:在某些场景中(如离线模式、模拟时间),可能需要展示"非系统时间的某个时间"。TextClock 不支持自定义时间源——它总是读取系统时间。这种情况下需要回到手动方案。

日期本地化:格式字符串中的 dddd(星期名)和 a(AM/PM)会自动跟随系统语言显示。中文环境下显示"星期五",英文环境下显示"Friday"。这是 TextClock 的隐藏功能——不需要额外配置即可实现基本的本地化。

这些扩展说明:TextClock 是"显示当前系统时间"场景的最佳方案,但它不是通用时间展示方案。秒表、倒计时、模拟时间等场景仍需要手动实现。理解 TextClock 的定位(系统时间自动展示)是正确使用它的关键。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐