一段式和三段式的区别

声明式范式把所有东西写在一个 .ets 文件里,结构、样式、逻辑混在一起。类 Web 范式回到经典的 Web 三段式:HML 管结构、CSS 管样式、JS 管逻辑,一个页面对应三个文件。

声明式范式:一个文件
  page.ets ── 结构 + 样式 + 逻辑

类 Web 范式:三个文件
  page.hml ── 结构(标签树)
  page.css ── 样式(选择器 + 属性)
  page.js  ── 逻辑(数据 + 事件处理)

这套写法对 Web 前端开发者几乎零学习成本,迁移已有 Web 应用也快。

一个完整的计数器页面

HML 结构文件

<!-- index.hml -->
<div class="container">
  <!-- 文本组件,数据来自 JS 里的 count -->
  <text class="count">{{ count }}</text>

  <!-- 按钮,点击触发 increase 方法 -->
  <button class="btn" onclick="increase">+1</button>
</div>

HML 用标签声明组件,{{ count }} 是数据绑定语法,onclick 绑定事件。

CSS 样式文件

/* index.css */
.container {
  flex-direction: column;      /* 纵向排列 */
  justify-content: center;     /* 垂直居中 */
  align-items: center;         /* 水平居中 */
  width: 100%;
  height: 100%;
}

.count {
  font-size: 48px;
  margin-bottom: 24px;
}

.btn {
  width: 120px;
  height: 48px;
}

CSS 用选择器定位组件再设置样式,和 Web 完全一致。

JS 逻辑文件

// index.js
export default {
  data: {
    count: 0  // 页面数据,HML 里的 {{ count }} 绑定的就是它
  },

  increase() {
    this.count++;  // 修改数据,UI 自动更新
  }
}

data 里声明页面数据,方法直接挂载在对象下供 HML 调用。改 this.count 后,绑定处自动刷新,这就是单向数据绑定。

整体架构:四层结构

类 Web 范式的架构和声明式范式不同,它多了一层前台框架:

┌────────────────┐
│  Application    │  JS FA 应用(开发者开发的 FA 应用)
├────────────────┤
│  Framework      │  页面解析、MVVM 模式、路由机制、自定义组件
├────────────────┤
│  Engine         │  动画解析、DOM 树构建、布局计算、渲染命令、事件管理
├────────────────┤
│  Porting Layer  │  平台抽象:事件对接、渲染管线、生命周期
└────────────────┘

这里的 Framework 层提供 MVVM(Model-View-ViewModel)开发模式——data 是 Model,HML 是 View,框架负责把两者绑定起来。Engine 层负责构建 DOM 树和布局计算,这正是声明式范式省掉的部分,也是类 Web 范式性能略逊的原因。

ArkUI.Full 和 ArkUI.Lite 怎么选

类 Web 范式内部又分两个版本:

版本定位组件能力面向设备
ArkUI.Full完整版完整容器/基础/媒体/画布/栅格/SVG 组件 + 自定义组件手机、平板等
ArkUI.Lite轻量版(Full 的子集)部分核心容器、基础、基础画布组件运动手表等资源受限设备

选 Full 还是 Lite 看设备。面向手表的轻量应用用 Lite,功能复杂交互丰富的应用用 Full。Lite 是 Full 的子集,意味着 Lite 里能写的组件 Full 里都能写。

单向数据绑定的边界

类 Web 范式是"单向数据绑定"——数据变了 UI 更新,但 UI 变化不会自动写回数据。所以输入框这类场景要手动监听:

export default {
  data: {
    username: ''
  },

  // 输入框内容变化时回调
  onUsernameChange(e) {
    this.username = e.value;  // 手动把输入同步回数据
  }
}

声明式范式里 @State 是双向感知的(数据驱动 UI,事件回调写回数据),类 Web 范式里这个"写回"要自己在事件里做,这就是单向和双向在开发体验上的差别。

什么时候还用类 Web 范式

主推的声明式范式功能更强性能更好,但类 Web 范式没有废弃,适用于:

  1. Web 开发团队转岗:团队全是 Web 前端,类 Web 范式上手最快
  2. 迁移已有 Web 应用:HML/CSS/JS 结构接近,改造工作量小
  3. 简单的中小型应用:界面不复杂,不需要声明式的高级状态管理
  4. FA 模型卡片:FA 模型的卡片只支持类 Web 范式

除此之外,新项目都建议走声明式。

两条容易忽略的通则

  1. this 绑定:方法里用 this.count 访问数据,注意方法被调用时 this 的指向。用箭头函数或确保方法在 JS 对象下正常绑定。

  2. 组件属性命名:HML 组件属性不少和 Web 有差异,不能想当然。写之前查一下对应组件的属性文档,别用 Web 的惯性去套。

一点实战体会哦

类 Web 范式适合快速出原型。但你如果打算做长期维护的应用,还是尽早转声明式——数据驱动 UI 的写法在状态多了之后明显更省心,不用在 JS 里手动管理一堆 DOM 更新。两者学了不冲突,搞清楚差异,选型时心里有数就行。

Logo

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

更多推荐