HarmonyOS-JS-UI
HarmonyOS JS UI
一、简介
什么是鸿蒙
鸿蒙操作系统 (HarmonyOS、鸿蒙OS) 是一款面向全场景的分布式操作系统。其开源项目为OpenHarmony。
历史
- 2012 年,华为开始规划自有操作系统“鸿蒙”
- 2019 年 8 月 9 日,华为在发布鸿蒙 1.0
- 2020 年 9 月 10 日,华为发布鸿蒙 2.0
- 2021 年 6 月 2 日,鸿蒙正式商用(华为正式发布 HarmonyOS 2 及多款搭载 HarmonyOS 2 的新产品)
鸿蒙的三大特征
- 超级小程序
- H5 只能使用浏览器的功能
- 小程序可以调用微信的功能(扫码、拍照、定位、查通讯录)
- 鸿蒙可以调用系统级别的功能(线程),而且可以调用其他设备的功能
- 可剪裁系统
- 可以跑在手机、平板、电视、可穿戴设备、智能硬件和⻋载系统上
- 鸿蒙可以根据系统(芯片)的算力,选择性地运行整个系统的某些部分
- 模改通讯协议
- IoT 互通互联的标准语言(手机,微波炉,冰箱,汽⻋,手表,耳机)
- 类似普通话,统一了方言
有用的网站
鸿蒙官网:
鸿蒙系统开发者:
华为开发者:
在线体验:
Gitee:
JS API:
储备知识
- 熟悉前端技术栈(HTML、CSS、JS)
- 熟悉微信小程序
- 熟悉 Vue
- 有安卓开发经验更好
二、系统架构
鸿蒙系统架构一共分四层:应用层、框架层、系统服务层、内核层。
内核层
- 内核子系统:HarmonyOS 采用多内核设计,支持针对不同资源受限设备选用适合的 OS内核。内核抽象层(KAL,Kernel Abstract Layer)通过屏蔽多内核差异,对上层提供基础的内核能力,包括进程/线程管理、内存管理、文件系统、网络管理和外设管理等。
- 驱动子系统:硬件驱动框架(HDF)是 HarmonyOS 硬件生态开放的基础,提供统一外设访问能力和驱动开发、管理框架。
系统服务层
系统服务层是 HarmonyOS 的核心能力集合,通过框架层对应用程序提供服务。该层包含以下几个部分:
- 系统基本能力子系统集:为分布式应用在 HarmonyOS 多设备上的运行、调度、迁移等操作提供了基础能力,由分布式软总线、分布式数据管理、分布式任务调度、方舟多语言运行时、公共基础库、多模输入、图形、安全、AI 等子系统组成。其中,方舟运行时提供了C/C++/JS 多语言运行时和基础的系统类库,也为使用方舟编译器静态化的Java程序(即应用程序或框架层中使用Java语言开发的部分)提供运行时。
- 基础软件服务子系统集:为 HarmonyOS 提供公共的、通用的软件服务,由事件通知、电话、多媒体、DFX(Design For X) 、MSDP & DV 等子系统组成。
- 增强软件服务子系统集:为 HarmonyOS 提供针对不同设备的、差异化的能力增强型软件服务,由智慧屏专有业务、穿戴专有业务、IoT 专有业务等子系统组成。
- 硬件服务子系统集:为 HarmonyOS 提供硬件服务,由位置服务、生物特征识别、穿戴专有硬件服务、IoT 专有硬件服务等子系统组成。
根据不同设备形态的部署环境,基础软件服务子系统集、增强软件服务子系统集、硬件服务子系统集内部可以按子系统粒度裁剪,每个子系统内部又可以按功能粒度裁剪。
框架层
框架层为 HarmonyOS 应用开发提供了 Java/C/C++/JS 等多语言的用户程序框架和 Ability框架,两种 UI 框架(包括适用于 Java 语言的 Java UI 框架、适用于 JS 语言的 JS UI 框架),以及各种软硬件服务对外开放的多语言框架 API。根据系统的组件化裁剪程度,HarmonyOS 设备支持的 API 也会有所不同。
应用层
应用层包括系统应用和第三方非系统应用。HarmonyOS 的应用由一个或多个 FA(Feature Ability)或 PA(Particle Ability)组成。其中,FA 有 UI 界面,提供与用户交互的能力;而 PA无 UI 界面,提供后台运行任务的能力,以及统一的数据访问抽象。FA 在进行用户交互时所需的后台数据访问,也需要由对应的 PA 提供支撑。基于 FA/PA 开发的应用,能够实现特定的业务功能,支持跨设备调度与分发,为用户提供一致、高效的应用体验。
JS UI 框架架构
JS UI 框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(Porting Layer)。
详情查看:
应用层
表示开发者使用 JS UI 框架开发的 FA 应用。
这里的 FA 应用特指 JS FA 应用。使用 Java开发FA应用请参考。
前端框架层
主要完成前端⻚面解析,以及提供 MVVM(Model-View-ViewModel)开发模式、⻚面路由机制和自定义组件等能力。
引擎层
主要提供动画解析、DOM(Document Object Model)树构建、布局计算、渲染命令构建与绘制、事件管理等能力。
适配层
主要完成对平台层进行抽象,提供抽象接口,可以对接到系统平台。比如:事件对接、渲染管线对接和系统生命周期对接等。
三、搭建开发环境
DevEco Studio
详情查看:
简介
DevEco Studio 是面向全场景多设备,提供一站式的分布式应用开发平台,支持分布式多端开发、分布式多端调测、多端模拟仿真,全方位的质量与安全保障。
环境要求
下载
下载地址:
目前提供 Mac 和 Windows 两大主流操作系统。针对自己的操作系统,下载对应的安装包即可(以下内容是在 Mac 上的安装截图)
安装
安装过程
具体步骤
步骤 | 操作步骤 | 操作指导 | 说明 |
---|---|---|---|
1 | 软件安装 | 安装DevEco Studio | |
2 | 配置开发环境 | 网络不能直接访问Internet,需要通过代理服务器才可以访问的情况下需要设置。如果无需代理即可访问Internet,可跳过该步骤。 | |
3 | 配置开发环境 | 网络不能直接访问Internet,需要通过代理服务器才可以访问的情况下需要设置。如果无需代理即可访问Internet,可跳过该步骤。 | |
4 | 配置开发环境 | 网络不能直接访问Internet,需要通过代理服务器才可以访问的情况下需要设置。如果无需代理即可访问Internet,可跳过该步骤。 | |
5 | 配置开发环境 | - | |
6 | 运行HelloWorld | 使用模拟器运行Demo工程,验证环境是否已经配置完成。 | |
7 | 运行HelloWorld | 使用模拟器运行Demo工程,验证环境是否已经配置完成。 |
执行安装
运行
SDK 组件安装
协议许可,点击 Accept,然后 Next
安装中(下载组件),等待…
安装完成后,点击 done。然后进入欢迎界面。左侧有四个菜单
- 创建鸿蒙项目
- 打开项目
- 在版本控制中获取
- 导入鸿蒙示例
接下来,我们可以点击第一个菜单(Create HarmonyOS Project),去创建一个项目。
初始化项目
点击欢迎⻚的 Create HarmonyOS Project
这里我选择 List Tab Ability(JS)
四、初始化项目
初始化完成后,就会看到如下界面(如此熟悉的目录的代码,跟小程序⻓得很像有木有~)
查看效果
点击 右侧的 Previewer 查看效果(或者 View -> Tool Windows -> Previewer )
五、安装模拟器
打开 Device Manager
注册并登录
如果没有注册,请先注册华为开发者账号(注册地址: );
如果没有登录,请先登录。登录后,会看到如下⻚面
实名认证
点击 Go Authentication 会看到下面的弹窗。然后点击 here,然后会跳转到华为开发者网站。
在华为开发者网站,注册成为开发者。
是否有敏感应用上架?
- 选择 是 ,会弹出银行卡认证的⻚面(后续需要支付相关的功能)
- 选择 否 ,推荐银行卡认证(不强制);但是,我们可以选择身份证认证。
选择 是,进行银行卡实名认证( 3 分钟 - 认证速度快),认证成功后的效果如下:
选择 否,然后进行身份证认证(1-2个工作日 - 认证速度慢)。
填写基本信息,上传身份证
提到并等待审核
安装模拟器
账户认证通过后,就可以在 DevEco 中添加模拟器了。
Tools -> Device Manager
安装后,看到如下效果
点击运行,可能查看项目在模拟器上的运行效果。
模拟器(Simulator)与预览器(Previewer)的区别:
- 预览器支持热更新,模拟器不支持热更新
- 预览器中不能直接返回接口数据,模拟器可以返回接口数据
六、汉化菜单
鸿蒙操作系统刚刚推出,为了更快的面向国际市场,编辑器默认采用英文。下面介绍一下汉化方法。
操作步骤
- 点选菜单 File -> Settings,
- 然后点选 Plugins -> Marketplate,
- 然后搜索 Chinese,
- 然后选择 Chinese(Simplified)Language Pack / 中文语言包。
- 然后点击 install 执行安装
安装完成后重启 IDE
重启后的效果
可以看到,大部分的菜单都汉化了
七、JS 框架
详情查看:
目录结构
详情查看:
实例目录
单实例目录
多实例目录
文件(目录)介绍
作用
- app.js 全局入口文件
- pages 存放⻚面
- common 公共资源
- resources 资源配置文件
- i18n 多语言目录
- share 多实例共享资源目录(5+)
注意:
如下文件夹是开发保留文件夹,不可重命名:
share
如果 share 中的资源和实例 (default) 中的资源文件同名且目录一致时,实例中资源的优先级高于share 中资源的优先级。
其他文件,可以根据开发需要自行创建。
访问规则
应用资源可通过绝对路径或相对路径的方式进行访问,本开发框架中绝对路径以"/“开头,相对路径以”./“或”…/"。具体访问规则如下:
- 引用代码文件,需使用相对路径,比如:…/common/utils.js。
- 引用资源文件,推荐使用绝对路径。比如:/common/xxx.png。
- 公共代码文件和资源文件推荐放在 common 下,通过以上两条规则进行访问。
- CSS 样式文件中通过 url() 函数创建 数据类型,如:url(/common/xxx.png)。
⻚面文件
⻚面中文件分类如下:
- .hml 描述⻚面的布局结构。
- .css 描述⻚面样式。
- .js 用于处理⻚面和用户的交互。
resources
详情查看:
1 resources
2 |---base // 默认存在的目录
3 | |---element
4 | | |---string.json
5 | |---media
6 | | |---icon.png
7 |---en_GB-vertical-car-mdpi // 限定词目录示例,需要开发者自行创建
8 | |---element
9 | | |---string.json
10 | |---media
11 | | |---icon.png
12 |---rawfile // 默认存在的目录
resources 目录分类
资源组目录
资源文件的使用: [https://developer.harmonyos.com/cn/docs/documentation/doc-
guides/basic-resource-file-example-0000001051733014]( )
八、配置文件
config.json
简介
详情查看:
建议在 DevEco 中,以可视化窗口的方式,来理解各配置项的含义
应用的每个 HAP 的根目录下都存在一个“config.json”配置文件,文件内容主要涵盖以下三个方面:
- 应用的全局配置信息,包含应用的包名、生产厂商、版本号等基本信息。
- 应用在具体设备上的配置信息,包含应用的备份恢复、网络安全等能力。
- HAP 包的配置信息,包含每个 Ability 必须定义的基本属性(如包名、类名、类型以及Ability 提供的能力),以及应用访问系统或其他应用受保护部分所需的权限等。
config.json 采用 JSON 格式。即内容都是有 属性: 值 组成的
- 属性,出现顺序不分先后,且每个属性最多只允许出现一次。
- 值,每个属性的值为JSON的基本数据类型(数值、字符串、布尔值、数组、对象或者null类型)。如果属性值需要引用资源文件,可参⻅资源文件。
常用配置
详情查看:
module
以下为 module 的配置想
申请权限
reqPermissions
1 {
2 "module": {
3 "reqPermissions": [
4 {
5 "name": "ohos.permission.CAMERA",
6 "reason": "$string:permreason_camera",
7 "usedScene":
8 {
9 "ability": ["com.mycamera.Ability", "com.myca
mera.AbilityBackground"],
10 "when": "always"
11 }
12 },{
13 ...
14 }
15 ]
16 }
17 }
defPermissions
1 {
2 "module": {
3 "defPermissions": [
4 {
5 "name": "com.myability.permission.MYPERMISSION",
6 "grantMode": "system_grant",
7 "availableScope": ["signature"]
8 }, {
9 ...
10 }
11 ]
12 }
13 }
js
pages
1 "pages": [
2 "pages/index/index",
3 "pages/detail/detail"
4 ]
注意:
pages 列表中第一个⻚面是应用的首⻚,即 entry 入口。
⻚面文件名不能使用组件名称,比如:text.hml、button.hml 等。
name
JS 实例名称
window
window 用于设置窗口配置。对于屏幕适配问题,有 2 种配置方法:
指定 designWidth(屏幕逻辑宽度,在手机和智慧屏上默认 720px,智能穿戴默认454px),所有与大小相关的样式(例如width、font-size)均以 designWidth 和实际屏幕宽度的比例进行缩放。
例如在 designWidth 为 720 时,如果设置 width 为100px时,在实际宽度为 1440 物理像素的屏幕上,width 实际渲染像素为 200 物理像素。
设置 autoDesignWidth 为 true,此时 designWidth 字段将会被忽略,渲染组件和布局 时按屏幕密度进行缩放。屏幕逻辑宽度由设备宽度和屏幕密度自动计算得出,在不同设备上可能不同,请使用相对布局来适配多种设备。
例如:在 466*466 分辨率,320dpi 的设备上,屏幕密度为 2 (以160dpi为基准),1px等于渲染出的 2 物理像素。
配置示例
详情参考:
九、生命周期
应用生命周期
onCreate:应用启动时调用
onDestroy:应用销毁时调用
⻚面生命周期
详情查看:
⻚面 A 的生命周期接口的调用顺序
打开⻚面 A:onInit() -> onReady() -> onShow() -> onActive()
在⻚面 A 打开⻚面 B:onInactive() -> onHide()
从⻚面 B 返回⻚面 A:onShow() -> onActive()
退出⻚面 A:onBackPress() -> onInactive() -> onHide() -> onDestroy()
⻚面隐藏到后台运行:onInactive() -> onHide()
⻚面从后台运行恢复到前台:onShow()
十、路由与导航
在 config.json 中声明路由
1 {
2 // ...
3 "module": {
4 "js": [
5 {
6 // 声明⻚面路由
7 "pages": [
8 "pages/index/index",
9 "pages/details/details",
10 "pages/comp/comp"
11 ],
12 "name": "default",
13 "window": {
14 "designWidth": 720 ,
15 "autoDesignWidth": false
16 }
17 }
18 ]
19 }
20 }
在 pages 目录下声明对应的三个文件
声明导航
引入 router
1 import router from '@system.router';
声明导航方法
1 export default {
2 // ...
3
4 launch: function () {
5 router.push({
6 uri: 'pages/details/details',
7 });
8 }
9 }
除了上面的 push 方法以外,还有如下方法。
十一、JS 语法
详情查看:
支持 ES 6 语法(但不支持最新的 ES 语法)
鸿蒙 JS 是参考 Vue 2 封装的
JS 应用
$def
在⻚面中,通过 this.
a p p . app.
a
pp
. def,获取在 app.js 中暴露的对象
数据绑定
data | public:类型是对象或者函数
private:数据只能由当前⻚面修改
数据修改
this.
s e t ( ′ k e y ′ , v a l u e ) ; t h i s . set(‘key’, value); this.
se
t
(
′
k
e
y
′
,
v
a
l
u
e
)
;
t
hi
s
. delete(‘key’);
获取 DOM 元素
$refs
1 // index.hml
2 <text ref="target" >内容</div>
3
4 // index.js
5 const t = this.$refs.target; // 获取 ref 属性为 target 的 DOM 元素
$element
1 // index.hml
2 <text id="target" >内容</div>
3
4 // index.js
5 const t = this.$element("target"); // 获取 id 属性为 target 的 DOM
元素
6
7 // 获取根组件对象
8 const t = this.$element();
JS 架构
- JS UI 框架
- 类 Web 范式编程的 UI 界面展示
- JS 应用开发框架
- 轻量级的 MVVM 实现(仿 Vue 2)
- JS 原生模块(NAPI)
- 实现 JS 与 C/C++ 代码互相访问
十二、HML 语法
HML(HarmonyOS Markup Language)是一套类 HTML 的标记语言,通过组件,事件构建出⻚面的内容。⻚面具备事件绑定、数据绑定、列表渲染、条件渲染和逻辑控制等能力。
详情查看:
十三、CSS 语法
详情查看:
基本语法
尺寸单位
只有像素和百分比
样式导入
@import ‘…/…/common/style.css’;
预编译
鸿蒙可以直接解析 sass 和 less(不需要自己安装解析插件)
屏幕适配
基于设计稿
假定设计稿尺寸(假定:720 px),终端尺寸(假定:1440 px)
则缩放比例为 1440 px /720 px = 2.0
根据缩放比例转换实际尺寸 100 px X 2.0 = 200 px
基于屏幕密度
屏幕密度(dpi = dots per inch 每英寸点数)
ldpi:低密度屏幕(~120dpi)(0.75 基准密度)
mdpi:中密度屏幕(~160dpi)(1.0 基准密度)
hdpi:高密度屏幕(~240dpi)(1.5 基准密度)
xhdpi:加高密度屏幕(~320dpi)(2.0 基准密度)
xxhdpi:超超高密度屏幕(~480dpi)(3.0 基准密度)
xxxhdpi:超超超高密度屏幕(~640dpi)(4.0 基准密度)
适配原理
根据基准密度转换实际尺寸(100 px X 2.0 = 200 px)
十四、多语言支持
详情查看:
- i18n 目录下存放语言包
- 语言-地区.json(zh-CN.json)
- $t() 获取对应的内容
- 切换系统语言时(模拟器或真机中),可以看到效果
十五、组件
组件是用来展示⻚面内容的,其功能定位与 HTML 标签相同。
需要强调的是, 华为提供的组件不是运行在浏览器环境下的 ,华为的组件,更像是小程序的组件。
但是,为了降低学习成本,华为提供的组件名称,大部分参考 HTML 标签的命名。例如:button,div,
input 等。虽然这些组件名称与 HTML 标签名一样,但属性和使用方式不尽相同。具体以官方文档为准。
基础组件
基础组件提供了基本的内容展示功能,是最常用的一些组件。
按钮
button
提供按钮组件,包括胶囊按钮、圆形按钮、文本按钮、弧形按钮、下载按钮。
详情查看:
toggle
状态按钮
详情查看:
piece
一种块状的入口,可包含图片和文本。常用于展示收件人,例如:邮件收件人或信息收件人。
详情查看:
文本
text
用来显示文本信息
详情查看:
span
作为
<text>
的子组件提供文本修饰能力
详情查看:
marquee
以跑⻢灯效果展示一行文本
详情查看:
textarea
显示多行文本
详情查看:
label
标签组件
详情查看:
图片
image
用来渲染展示图片
详情查看:
image-animator
图片帧动画
详情查看:
表单
input
输入框,包括单选框,多选框,按钮和单行文本输入框。
详情查看:
select
下拉选择组件
详情查看:
option
可以作为
<select>
和
<menu>
的子组件来展示内容
详情查看:
search
搜索组件
详情查看:
switch
开关选择器
详情查看:
rating
评分条
详情查看:
picker
选择器,类型支持普通选择器,日期选择器,时间选择器,时间日期选择器,多列文本选择器。
详情查看:
picker-view
嵌入⻚面的滑动选择器
详情查看:
导航
menu
提供菜单组件,作为临时性弹出窗口,用于展示用户可执行的操作。其子组件是 option
详情查看:
toolbar
工具栏
详情查看:
toolbar-item
工具栏子项
详情查看:
其他
slider
滑动条
详情查看:
progress
进度条
详情查看:
divider
分割器,用来分割不同的内容
详情查看:
chart
图标组件
详情查看:
qrcode
生成并显示二维码
详情查看:
容器组件
div
用作⻚面结构的根节点或将内容进行分组。
详情查看:
stack
堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。(相当于 z-index)
详情查看:
badge
徽章
详情查看:
列表
列表包含一系列相同宽度的列表项。适合连续、多行呈现同类数据,例如图片和文本。
详情查看:
list-item
<list>
的子组件,用来展示列表具体item
详情查看:
list-item-group
<list>
的子组件,用来展示分组,宽度默认充满list组件。
详情查看:
栅格
提供栅格布局效果,通过栅格系统进行元素布局,主要提供
<grid-container><grid-row><grid-col>
栅格容器组件。
栅格系统有 Margins,Gutters,Columns 三个属性。
- Margins:是用来控制元素距离屏幕最边缘的距离关系,可以根据设备的不同尺寸,定义不同的Margin 值作为断点系统中的统一规范。
- Gutters:是用来控制元素和元素之间的距离关系,可以根据设备的不同尺寸,定义不同的Gutters值作为断点系统中的统一规范。为了保证较好的视觉效果,Gutters 通常不会大于Margins 的取值。
- Columns:是用来辅助布局的主要定位工具,不同的屏幕尺寸匹配不同的 Columns 数量来辅助布局定位。Columns 的宽度在保证 Margins 和 Gutters 符合规范的情况下,根据实际设备的宽度和 Columns 数量自动计算每一个 Columns 的宽度。
格断点系统
栅格系统定义了不同水平宽度设备对应 Columns 的数量关系,形成了一套断点规则定义。
栅格系统以水平分辨率值作为断点依据,不同的设备根据自身当前水平宽度 px 值(配置了autoDesignWidth 为 true) 在不同的断点范围内的情况,显示不同数量的栅格数。
- xs: 0<水平分辨率<320 时:2 Columns 栅格;
- sm: 320<=水平分辨率<600 时:4 Columns 栅格;
- md: 600<=水平分辨率<840 时:8 Columns 栅格;
- lg: 840 <= 水平分辨率时:12 Columns 栅格;
grid-container
栅格布局容器根节点,包含 grid-row 与 gird-col 进行栅格布局。
详情查看:
grid-row
grid-row 是栅格布局容器 grid-container 的子容器组件,使用 flex 横向布局,排列每个grid-col 容器,justify-content 与 align-items 默认为 flex-start,支持折行显示。
详情查看:
grid-col
grid-col 是栅格布局容器 grid-row 的子容器组件。
详情查看:
选项卡
tabs
选项卡容器
详情查看:
tab-bar
选项卡菜单
详情查看:
tab-content
选项卡内容
详情查看:
弹窗
dialog
自定义弹窗
详情查看:
popup
气泡弹窗
详情查看:
panel
可滑动面板。提供一种轻量的内容展示的窗口,可方便的在不同尺寸中切换。属于弹出式组件。
详情查看:
步骤导航
stepper
步骤导航器。当完成一个任务需要多个步骤时,可以使用步骤导航器展示当前进展。
详情查看:
stepper-item
步骤导航子组件
详情查看:
轮播图
轮播图组件
swiper
详情查看:
下拉刷新容器
下拉刷新容器。
refresh
详情查看:
通用组件
媒体查询
基本语法
1 @media [media-type] [and|not|only] [(media-feature)] {
2 CSS-Code;
3 }
@media screen and (round-screen: true) { … } // 当设备屏幕是圆形时条件成立
@media (max-height: 800) { … } // 范围查询,CSS level 3 写法
@media (height <= 800) { … } // 范围查询,CSS level 4 写法,与 CSS level3 写法等 价
@media screen and (device-type: tv) or (resolution < 2) { … } // 同时包含媒体类型和多个媒体特征的多条件复杂语句查询
引入资源
1 @import url [media-type] [and|not|only] [(media-feature)];
2
3 # 例如
4 @import '../common/style.css' screen and (min-width: 600 ) and (max
-width: 1200 );
操作符
and、or、not、only用于构成复杂媒体查询,也可以通过comma(,)将其组合起来。
在MediaQuery Level 4中引入了范围查询,使其能够使用max-,min-的同时,也支持了 <=,>=,<,>操作符。
媒体特征
自定义组件
自定义组件通过element引入到宿主⻚面。
1 <element name='comp' src='../../common/component/comp.hml'></eleme
nt>
2 <div>
3 <comp prop1='xxxx' @child1="bindParentVmMethod"></comp>
4 </div>
- name 属性指自定义组件名称(非必填),组件名称对大小写不敏感,默认使用小写。src 属性指自定义组件 hml 文件路径(必填),若没有设置 name 属性,则默认使用 hml 文件名作为组件名。
- 事件绑定:自定义组件中绑定子组件事件使用(on|@)child1)语法,子组件中通过this.$emit(‘child1’, { params: ‘传递参数’ }) 触发事件并进行传值,父组件执行 bindParentVmMethod 方法并接收子组件传递的参数。
子组件中使用驼峰命名法命名的事件,在父组件中绑定时需要使用短横线分隔命名形式,例如:@children-event表示绑定子组件的 childrenEvent 事件,如 @children-event=“bindParentVmMethod”。
事件传递
子组件
模板文件
1 <!-- comp.hml -->
2 <div class="item">
3 <text class="text-style" onclick="childClicked">点击这里查看隐藏文
本</text>
4 <text class="text-style" if="{{showObj}}">hello world</text>
5 </div>
JS 文件
1 // comp.js
2 export default {
3 data: {
4 showObj: false,
5 },
6 childClicked () {
7 this.$emit('eventType1');
8 this.showObj = !this.showObj;
9 },
10 }
父组件
模板文件
1 <!-- xxx.hml -->
2 <element name='comp' src='../../common/component/comp.hml'></eleme
nt>
3 <div class="container">
4 <comp @event-type1="textClicked"></comp>
5 </div>
JS 文件
1 // xxx.js
2 export default {
3 textClicked () {},
4 }
参数传递
子组件
模板文件
1 <!-- comp.hml -->
2 <div class="item">
3 <text class="title-style">{{compProp}}</text>
4 </div>
JS 文件
1 // comp.js
2 export default {
3 props: ['compProp'],
4 }
父组件
1 <!-- xxx.hml -->
2 <element name='comp' src='../../common/component/comp/comp.hml'></
element>
3 <div class="container">
4 <comp comp-prop="{{title}}"></comp>
5 </div>
父组件 comp-prop => 子组件 compProp
设置默认值
1 // comp.js
2 export default {
3 props: {
4 compProp: {
5 default: '123',
6 },
7 },
8 }
当用户没有在父组件中设置 comp-prop 的值时,会默认显示 123
数据单向性
父子组件之间数据的传递是单向的,只能从父组件传递给子组件,子组件不能直接修改父组件传递下来的值,可以将 props 传入的值用 data 接收后作为默认值,再对 data 的值进行修改。
1 // comp.js
2 export default {
3 props: ['compProp'],
4 data() {
5 return {
6 count: this.compProp,
7 };
8 },
9 onClick() {
10 this.count = this.count + 1 ;
11 },
12 }
$watch
监控数据变化
1 // comp.js
2 export default {
3 props: ['title'],
4 onInit() {
5 this.$watch('title', 'onPropertyChange');
6 },
7 onPropertyChange(newV, oldV) {
8 console.info('title 属性变化 ' + newV + ' ' + oldV);
9 },
10 }
computed
计算属性变化
自定义组件中,经常需要在读取或设置某个属性时,进行预先处理,此时,就需要使用 computed 字段。computed 中的 getter 和 setter 方法,在属性读写的时候进行触发,使用方式如下:
1 // comp.js
2 export default {
3 props: ['title'],
4 data() {
5 return {
6 objTitle: this.title,
7 time: 'Today',
8 };
9 },
10 computed: {
11 message() {
12 return this.time + ' ' + this.objTitle;
13 },
14 notice: {
15 get() {
16 return this.time;
17 },
18 set(newValue) {
19 this.time = newValue;
20 },
21 },
22 },
23 onClick() {
24 console.info('get click event ' + this.message);
25 this.notice = 'Tomorrow';
26 },
27 }
这里声明的第一个计算属性 message 默认只有 getter 函数,message 的值会取决于objTitle 的值的变化。getter 函数只能读取不能改变值,当需要赋值给计算属性时,可以提供一个 setter 函数,如示例中的 notice。
事件参数
子组件也可以通过绑定的事件向上传递参数,在自定义事件上添加传递参数的示例如下:
子组件
模板文件
1 <!-- comp.hml -->
2 <div class="item">
3 <text class="text-style" onclick="childClicked">点击这里查看隐藏文
本</text>
4 <text class="text-style" if="{{showObj}}">hello world</text>
5 </div>
JS 文件
1 // comp.js
2 export default {
3 childClicked () {
4 this.$emit('eventType1', {text: '收到子组件参数'});
5 this.showObj = !this.showObj;
6 },
7 }
父组件
模板文件
1 <!-- xxx.hml -->
2 <div class="container">
3 <text>父组件:{{text}}</text>
4 <comp @event-type1="textClicked"></comp>
5 </div>
JS 文件
1 // xxx.js
2 export default {
3 data: {
4 text: '开始',
5 },
6 textClicked (e) {
7 this.text = e.detail.text;
8 },
9 }
插槽
匿名插槽
父组件:
<tag><text>
内容
</text></tag>
子组件:
<slot></slot>
具名插槽
父组件:
<tag><text slot="slotname">
内容
</text></tag>
子组件:
<slot name="slotname"></slot>
十六、接口
同步
同步方法调用后,必须等到返回结果,然后才能继续后续操作。
没有回调函数或有 Sync 后缀的,一般是同步操作
1 var info = app.getInfo();
2 console.log(JSON.stringify(info));
异步
异步方法调用时,不会阻碍调用者的工作。业务执行完成后,会调用开发者提供的回调函数。
有回调函数或无 Sync 后缀的,一般是异步操作
1 device.getInfo({
2 success: function(data) {
3 console.log('成功,设备品牌:' + data.brand);
4 },
5 fail: function(data, code) {
6 console.log('失败. 错误码:'+ code + '; 错误信息: ' + data);
7 },
8 complete: function() {
9 console.log('get info complete');
10 },
11 });
订阅
订阅之后,该回调函数会在完成时,或者事件变化时再次进行回调;可以执行多次
例如:订阅地理位置,位置发生变化时,会再次执行回调函数。
1 geolocation.subscribe({
2 success: function(data) {
3 console.log('get location. latitude:' + data.latitude);
4 },
5 fail: function(data, code) {
6 console.log('fail to get location. code:' + code);
7 },
8 });
十七、 基本功能
应用上下文
详情查看:
⻚面路由
详情查看:
弹窗
详情查看:
定时器
详情查看:
十八、网络功能
上传下载
详情查看:
数据请求
详情查看:
十九、文件数据
数据存储
详情查看:
引入
1 import storage from '@system.storage';
使用
1 // 设置内容
2 storage.set({
3 key: 'storage_key',
4 value: 'storage value',
5 success: function() {
6 console.log('call storage.set success.');
7 },
8 fail: function(data, code) {
9 console.log('call storage.set fail, code: ' + code + ', data:
' + data);
10 },
11 });
12
13 // 获取内容
14 storage.get({
15 key: 'storage_key',
16 success: function(data) {
17 console.log('call storage.get success: ' + data);
18 },
19 fail: function(data, code) {
20 console.log('call storage.get fail, code: ' + code + ', data:
' + data);
21 },
22 complete: function() {
23 console.log('call complete');
24 },
25 });
26
27 // 删除内容
28 storage.delete({
29 key: 'Storage1',
30 success: function() {
31 console.log('call storage.delete success.');
32 },
33 fail: function(data, code) {
34 console.log('call storage.delete fail, code: ' + code + ', da
ta: ' + data);
35 },
36 });
37
38 // 清空内容
39 storage.clear({
40 success: function() {
41 console.log('call storage.clear success.');
42 },
43 fail: function(data, code) {
44 console.log('call storage.clear fail, code: ' + code + ', dat
a: ' + data);
45 },
46 });
文件存储
详情查看:
存储目录
引入
1 import file from '@system.file';
使用
详情查看:
二十、 系统功能
通知消息
详情查看:
引入
1 import notification from '@system.notification';
使用
1 notification.show({
2 contentTitle: 'title info',
3 contentText: 'text',
4 clickAction: {
5 bundleName: 'com.huawei.testapp',
6 abilityName: 'notificationDemo',
7 uri: '/path/to/notification',
8 },
9 });
震动
详情查看:
引入
1 import vibrator from '@system.vibrator';
使用
1 vibrator.vibrate({
2 mode: 'short',
3 success() {
4 console.log('success to vibrate');
5 },
6 fail(data, code) {
7 console.log('handle fail, data = ${data}, code = ${code}');
8 },
9 });
传感器
详情查看:
引入
1 import sensor from '@system.sensor';
权限
- 计步器:ohos.permission.ACTIVITY_MOTION
- 心率:ohos.permission.READ_HEALTH_DATA
- 加速度:ohos.permission.ACCELEROMETER
使用
1 // 观察加速度数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生效。
2 sensor.subscribeAccelerometer({
3 interval: 'normal',
4 success: function(ret) {
5 console.log('get data x:' + ret.x);
6 console.log('get data y:' + ret.y);
7 console.log('get data z:' + ret.z);
8 },
9 fail: function(data, code) {
10 console.error("subscribe accelerometer fail, code: ' + code +
', data: ' + data);
11 },
12 });
13
14 // 订阅罗盘数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生效。
15 sensor.subscribeCompass({
16 success: function(ret) {
17 console.log('get data direction:' + ret.direction);
18 },
19 fail: function(data, code) {
20 console.error("subscribe compass fail, code: ' + code + ', da
ta: ' + data);
21 },
22 });
23
24 // 订阅环境光线感应数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用
生效。
25 sensor.subscribeLight({
26 success: function(ret) {
27 console.log('get data intensity:' + ret.intensity);
28 },
29 fail: function(data, code) {
30 console.error('subscribe light fail, code: ' + code + ', dat
a: ' + data);
31 },
32 });
33
34 // 订阅计步传感器数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生
效。
35 sensor.subscribeStepCounter({
36 success: function(ret) {
37 console.log('get step value:' + ret.steps);
38 },
39 fail: function(data, code) {
40 console.log('subscribe step count fail, code:' + code + ', da
ta:' + data);
41 },
42 });
43
44 // 订阅气压传感器数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生
效。
45 sensor.subscribeBarometer({
46 success: function(ret) {
47 console.log('get data value:' + ret.pressure);
48 },
49 fail: function(data, code) {
50 console.log('subscribe barometer fail, code: ' + code + ', da
ta: ' + data);
51 },
52 });
53
54 // 订阅心率传感器数据变化。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生
效。
55 sensor.subscribeHeartRate({
56 success: function(ret) {
57 console.log('get heartrate value:' + ret.heartRate);
58 },
59 fail: function(data, code) {
60 console.log('subscribe heart rate fail, code: ' + code + ', d
ata: ' + data);
61 },
62 });
63
64 // 订阅设备佩戴状态。再次调用时,会覆盖前一次调用效果,即仅最后一次调用生效。
65 sensor.subscribeOnBodyState({
66 success: function(ret) {
67 console.log('get on-body state value:' + ret.value);
68 },
69 fail: function(data, code) {
70 console.log('fail to get on body state, code:' + code + ', da
ta: ' + data);
71 },
72 });
73
74 // 获取设备佩戴状态。
75 sensor.getOnBodyState({
76 success: function(ret) {
77 console.log('on body state: ' + ret.value);
78 },
79 fail: function(data, code) {
80 console.log('handling fail, message: ' + data + ', code: ' +
code);
81 },
82 });
地理位置
详情参考:
引入
1 import geolocation from '@system.geolocation';
权限
ohos.permission.LOCATION
使用
1 // 获取位置信息
2 geolocation.getLocation({
3 success: function(data) {
4 console.log('经度:' + data.longitude);
5 console.log('纬度:' + data.latitude);
6 },
7 fail: function(data, code) {
8 console.log('fail to get location. code:' + code + ', data:'
+ data);
9 },
10 });
网络状态
详情参考:
权限
- ohos.permission.GET_WIFI_INFO
- ohos.permission.GET_NETWORK_INFO
1 import network from '@system.network';
使用
1 network.getType({
2 success: function(data) {
3 console.log('success get network type:' + data.type);
4 },
5 fail: function(data, code) {
6 console.log('fail to get network type code:' + code + ', dat
a:' + data);
7 },
8 });
设备信息
详情参考:
使用
1 import device from '@system.device';
使用
1 device.getInfo({
2 success: function(data) {
3 console.log('Device brand:' + data.brand);
4 },
5 fail: function(data, code) {
6 console.log('Error code:'+ code + '; Error information: ' + da
ta);
7 },
8 });
屏幕亮度
详情参考:
使用
1 import brightness from '@system.brightness';
1 brightness.getValue({
2 success: function(data){
3 console.log('success get brightness value:' + data.value);
4 },
5 fail: function(data, code) {
6 console.log('get brightness fail, code: ' + code + ', data: '
+ data);
7 },
8 });y7
二十一、 官方 Demo
鸿蒙提供的一些具体应用实例。有代码,有文字介绍,有效果演示
详情查看:
JS 购物应用
详情查看:
JS 计步器卡片
详情查看:
分布式新闻分享
详情查看:
分布式亲自教育
详情查看: