第10章_HarmonyOs开发图解 用JS开发UI

98 阅读6分钟

第10章 HarmonyOs开发图解 用 JS 开发 UI

HarmonyOS 学习系统 | 阶段二:进阶实战期 建议学习时长:2-3 周


学习目标

序号能力
1理解 JS UI 声明式编程模型和 MVVM 架构
2掌握 hml/css/js 三件套的开发流程
3能实现数据绑定和事件处理
4了解 JS FA 调用 Java PA 的两种方式

核心图解

Java UI vs JS UI 对比图


内容讲解

10.1 JS UI 概述

如果你有网页开发经验,JS UI 会让你感到非常亲切:

  • .hml 文件 = HTML 文件——定义页面结构(但叫 hml 不是 html)
  • .css 文件 = CSS 文件——定义页面样式(跟 CSS 几乎一样)
  • .js 文件 = JavaScript 文件——定义业务逻辑(标准 ECMAScript)
  • AceAbility = Java FA 的 JS 版本——JS 页面的宿主
  • 数据绑定 {{ }} = Vue.js 的模板语法——变量变了界面自动更新
JS UI 的基础能力
能力说明
声明式编程类 HTML 和 CSS 声明式语言,避免编写 UI 状态切换代码
跨设备运行时自动映射到不同设备类型,开发者无感知
高性能针对声明式语法进行了渲染流程优化
JS UI 框架架构

JS UI 框架分为四层:

  1. 应用层 (Application Layer):开发者使用 JS UI 框架开发的 FA 应用
  2. 前端框架层 (Framework Layer):MVVM 开发模式、页面路由机制、自定义组件
  3. 引擎层 (Engine Layer):DOM 树构建、布局计算、渲染命令构建、事件管理
  4. 平台适配层 (Porting Layer):抽象接口,对接到系统平台
基准宽度
  • 手机和智慧屏:以 720px(逻辑像素)为基准宽度
  • 智能穿戴设备:以 454px 为基准宽度
  • 实际显示时会根据屏幕物理像素自动缩放

10.2 JS FA 开发

创建 JS FA 应用

创建工程时选择 Empty Ability(JS) 模板。JS FA 通过 AceAbility 类加载,在 config.json 中配置 js 字段指定页面路由。

"js": {
    "name": "default",
    "pages": [
        "pages/index/index"
    ]
}
AceAbility

AceAbility 是 JS FA 在 HarmonyOS 上运行环境的基类,继承自 Ability。默认代码:

public class MainAbility extends AceAbility {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
    }
}

如果修改了 config.json 中的 js.name,需要在 onStart() 中调用 setInstanceName():

@Override
public void onStart(Intent intent) {
    super.setInstanceName("JSComponentName");
    super.onStart(intent);
}
JS FA 开发目录结构
main/js/default/
├── i18n/                    # 国际化
│   ├── en-US.json
│   └── zh-CN.json
├── common/                  # 公共资源
│   └── images/
└── pages/
    └── index/
        ├── index.hml       # 页面结构
        ├── index.css       # 页面样式
        └── index.js        # 业务逻辑
三件套详解

index.hml(页面结构):

<div class="container">
    <text class="title">{{ title }}</text>
    <image src="{{ isPressed ? $r('app.media.liked') : $r('app.media.unliked') }}"
           class="like-img" onclick="toggleLike"></image>
    <text class="count">{{ count }}</text>
</div>

index.css(页面样式):

.container {
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
.title {
    font-size: 30px;
    color: #333333;
    margin-bottom: 20px;
}
.like-img {
    width: 100px;
    height: 100px;
}
.count {
    font-size: 24px;
    color: #e91e63;
    margin-top: 10px;
}

index.js(业务逻辑):

export default {
    data: {
        title: 'Hello HarmonyOS!',
        isPressed: false,
        count: 99
    },
    toggleLike() {
        this.isPressed = !this.isPressed;
        if (this.isPressed) {
            this.count++;
        } else {
            this.count--;
        }
    }
}

数据绑定机制:JS UI 采用 MVVM 模式,data 中的变量通过 {{ 变量名 }} 绑定到视图。当变量值发生变化时,视图自动更新——这和 Vue.js 的响应式原理类似。

10.3 JS UI 组件与布局

组件分类
分类组件
基础组件text、image、progress、rating、span、marquee、divider、search
容器组件div、list、list-item、stack、swiper、tabs、tab-bar、tab-content、refresh
媒体组件video
画布组件canvas
常用布局 CSS 属性
属性说明示例值
flex-direction排列方向column / row
justify-content主轴对齐center / flex-start / flex-end / space-between
align-items交叉轴对齐center / flex-start / flex-end / stretch
flex-wrap是否换行wrap / nowrap
flex-weight权重(占比)1 / 2 / 3

10.4 JS FA 调用 PA

JS UI 框架提供了 JS FA 调用 Java PA 的机制,支持两种调用方式:

方式生命周期通信方式适用场景
Ability独立 Ability 生命周期远程进程通信 (RPC)多 FA 调用、后台独立运行
Internal Ability与 FA 共进程内部函数调用对时延要求高的场景
JS 端调用 PA
import FeatureAbility from '@ohos.featureability';

export default {
    data: {
        result: '等待计算结果...'
    },
    play() {
        FeatureAbility.callAbility({
            bundleName: 'com.example.jsfacallpa',
            abilityName: 'PlayAbility',
            messageCode: 1001,
            data: { numbers: [1, 2, 3, 4, 5] },
            arity: 1
        }).then((data) => {
            this.result = '计算结果: ' + data.result;
        }).catch((error) => {
            this.result = '调用失败: ' + error;
        });
    }
}
Java PA 端处理
public class PlayAbility extends Ability {
    @Override
    public boolean onRemoteRequest(int code, MessageParcel data,
            MessageParcel reply, MessageOption option) {
        if (code == 1001) {
            // 解析参数
            String numbersStr = data.readString();
            // 执行计算
            int sum = 0;
            // ... 计算逻辑
            reply.writeString(String.valueOf(sum));
            return true;
        }
        return false;
    }
}

代码速查卡

特性Java UIJS UI
编程范式命令式声明式 (MVVM)
布局定义XML 文件HML 文件
样式定义XML 属性 / graphic XMLCSS 文件
数据绑定手动 findComponentById + setText自动 {{ 变量名 }}
宿主类Ability extends AbilityAceAbility extends Ability
页面单元AbilitySlice.hml + .css + .js 三件套
适合人群Java/Android 开发者前端/Web 开发者
跨设备适配需手动适配自动适配(720px 基准)
事件绑定setClickedListener()onclick="methodName"
调用 PA直接 Java 调用FeatureAbility.callAbility()

与 Android/iOS 对比

特性HarmonyOS JS UIAndroid (Jetpack Compose)iOS (SwiftUI)
编程语言JavaScriptKotlinSwift
编程范式声明式 MVVM声明式声明式
模板语法hml (类 HTML)@Composable 函数@ViewBuilder
样式定义CSS 文件Modifier 链式调用修饰符链式调用
数据绑定{{ }} 自动remember / state@State / @Binding
跨平台HarmonyOS 多设备Android 设备Apple 设备

⚠️ 踩坑回忆录

第一次写 JS FA 时,我直接把 HTML 语法搬过来了,写了 <div class="box" style="color:red">,结果样式完全没生效。后来才明白 hml 语法虽然类似 HTML 但不完全一样,内联样式要用 style 属性但语法有差异,而且有些 HTML 标签在 hml 中是不支持的。

另外,JS FA 的运行时和 Java FA 不同——Java FA 运行在方舟运行时上,JS FA 运行在 JS 引擎上,两者的生命周期管理也不一样,不能混用。如果你在 JS FA 中需要调用 Java 的能力,必须通过 FA 调用 PA 的机制来桥接。


必做实操任务

序号任务难度
1使用 Empty Ability(JS) 模板创建应用并运行★☆☆
2实现点赞按钮功能(数据绑定 + 事件处理)★★☆
3使用 list 组件实现一个简单的列表展示★★☆
4使用 tabs 组件实现多 Tab 页面切换★★☆
5实现 JS FA 调用 Java PA 的计算功能★★★

学习检查清单

  • 能说出 JS UI 框架的四层架构
  • 能创建 JS FA 工程并理解目录结构
  • 能实现数据绑定({{ }} 语法)
  • 能实现事件处理(onclick 等事件)
  • 能说出 hml/css/js 三件套各自的职责
  • 能解释 MVVM 模式在 JS UI 中的应用
  • 能实现 JS FA 调用 PA 的基本流程
  • 理解 Java UI 和 JS UI 的核心区别

阶段二学习路径

阶段二学习路径总结


进阶方向

  • 深入学习 JS UI 的自定义组件开发
  • 学习 swiper、refresh 等高级容器组件
  • 了解 JS UI 的页面路由(router)机制
  • 学习响应式布局和自适应屏幕