鸿蒙即 HarmonyOS ,是华为公司推出的支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备的分布式操做系统,而且它提供了多语言开发的 API,支持 Java、XML、C/C++、JS、CSS、HML(类 html 的鸿蒙本身的标记语言)等开发语言,并且它提供多种响应式布局方案,支持栅格化布局,可使用同一套代码部署在手机手表平板等多种不一样尺寸屏幕的设备上。javascript
开发鸿蒙软件须要用到 HUAWEI DevEco Studio,它提供了模板建立、开发、编译、调试、发布等服务。css
一、登陆 HarmonysOS 应用开发门户,点击右上角注册按钮,注册开发者账号。html
二、进入 HUAWEI DevEco Studio 产品页,登陆华为开发者帐号后下载 DevEco Studio 安装包并进行安装。前端
三、启动 DevEco Studio,根据工具引导下载 HarmonyOS SDK。 java
四、下载 HarmonyOS SDK 成功后会进入欢迎页,点击欢迎页中的 Configure > Settings 打开设置窗口,点击 Apparance&behavior > System settings > HarmonyOS SDK,选中 JS SDK 进行下载。 web
至此开发环境安装完成。json
点击菜单栏中的 File > New > New Project 选择须要开发的项目设备,而后选择 Empty Featrue Ability(JS) 后,点击 Next,此时会出现项目的信息配置
点击 Finish,一个新的项目就被建立出来了。canvas
使用 JS SDK 进行开发的话,须要关注的是 entry > src > main > js 文件夹,其中:小程序
i18n 目录下存放的是多语言的 json 文件数组
en-US.json 为英文模式展现的内容 zh-CN.json 为中文模式展现的内容
pages 下存放的是项目的多个页面,每一个页面都由 hml、js 和 css 组成
hml 文件定义了页面的布局、页面中用到的组件,以及这些组件的层级关系 js 文件定义了页面的业务逻辑,好比数据绑定、事件处理等 css 文件定义了 index 页面的样式
app.js 中存放的是全局的 js 逻辑和 app 的生命周期管理
除此以外,还能够本身建立 common 目录用于存放公共资源文件,好比:公共样式和公用方法。
生命周期分为应用的生命周期以及页面的生命周期
其中,应用的生命周期主要分为应用建立时调用的 onCreate,以及应用销毁时触发的 onDestroy。
而页面的生命周期分为:
因为JS UI只支持应用同时运行并展现一个页面,所以当应用从页面 A 跳转到页面 B 时,首先触发页面 A 的 onHide、onDestroy 函数,而后依次调用页面 B 的 onInit、onReady、onShow 函数来初始化和显示页面 B。
在 hml 文件中,组件分为容器组件、基础组件、媒体组件、画布组件、栅格组件,因为篇幅有限,这里只列举一下组件名称和对应的描述,感兴趣的同窗能够点击 组件文档 进行查阅。
组件名 | 描述 |
---|---|
div | 基础容器 |
list | 列表容器 |
list-item | list 的子组件,用来展现列表具体 item |
list-item-group | list 的子组件,用来展现分组,宽度默认充满 list 组件 |
badge | 新事件标记容器 |
dialog | 自定义弹窗容器 |
panel | 弹出式可滑动面板容器 |
popup | 气泡提示容器 |
refresh | 下拉刷新容器 |
stack | 堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件 |
stepper | 步骤导航器。当完成一个任务须要多个步骤时,可使用步骤导航器展现当前进展 |
stepper-item | 步骤导航器子组件,做为步骤导航器某一个步骤的内容展现组件 |
swiper | 滑动切换容器 |
tabs | tab 页标签切换容器 |
tab-bar | tabs 的子组件,用来展现 tab 的标签区 |
tab-content | tabs 的子组件,用来展现 tab 的内容区 |
组件名 | 描述 |
---|---|
image | 图片组件,用来渲染展现图片 |
image-animator | 图片帧动画播放器 |
text | 文本组件,用于展现文本信息 |
span | text 的子组件,提供文本修饰能力 |
textarea | 多行文本输入框 |
input | 交互式组件,包括单选框,多选框,按钮和单行文本输入框 |
button | 按钮组件,包括胶囊按钮、圆形按钮、文本按钮、弧形按钮、下载按钮 |
chart | 图表组件,用于呈现线形图、柱状图、量规图界面 |
divider | 提供分隔器组件,分隔不一样内容块/内容元素。可用于列表或界面布局 |
label | 为 input、button、textarea 组件定义相应的标注,点击该标注时会触发绑定组件的点击效果 |
marquee | 跑马灯组件,用于展现一段单行滚动的文字 |
menu | 菜单组件,做为临时性弹出窗口,用于展现用户可执行的操做 |
select | 下拉选择组件,可以让用户在多个选项之间选择 |
option | 可做为 menu 或 select 组件的子组件,用来展现具体项目 |
picker | 滑动选择器组件,类型支持普通选择器,日期选择器,时间选择器,时间日期选择器,多列文本选择器 |
picker-view | 嵌入页面的滑动选择器 |
piece | 一种块状的入口组件,可包含图片和文本,经常使用于展现收件人 |
progress | 进度条组件,用于显示内容加载或操做处理进度 |
qrcode | 二维码组件,用于生成并显示二维码 |
rating | 评分条组件 |
search | 搜索框组件,用于提供用户搜索内容的输入区域 |
slider | 滑动条组件,用来快速调节设置值,如音量、亮度等 |
switch | 开关组件,用于开启或关闭某个功能 |
toolbar | 工具栏组件,放在界面底部,用于展现针对当前界面的操做选项 |
toolbar-item | toolbar 子组件,用于展现工具栏上的一个操做选项 |
toggle | 状态按钮组件,用于从一组选项中进行选择 |
媒体组件暂时只有 video 组件一个,除了智能穿戴设备不支持外,手机、平板、智慧屏设备均支持该组件,它为设备提供了视频播放功能。
画布组件展现只有 canvas 组件一个,手机、平板、智慧屏、智能穿戴设备均支持该组件,它为设备提供了自定义绘制图形的能力。
组件名 | 描述 |
---|---|
grid-container | 栅格布局容器根节点 |
grid-row | grid-row 是栅格布局容器 grid-container 的子容器组件,使用 flex 横向布局,排列每一个 grid-col 容器,justify-content 与 align-items 默认为 flex-start,支持折行显示 |
grid-col | grid-row 的子容器组件 |
栅格系统有 Margins, Gutters, Columns 三个属性:
不一样的设备根据水平宽度 px,显示不一样数量的栅格数:
xs : 0px < 水平分辨率 < 320px:2 Columns 栅格;
sm : 320px <= 水平分辨率 < 600px:4 Columns 栅格;
md : 600px <= 水平分辨率 < 840px:8 Columns 栅格;
lg : 840px <= 水平分辨率:12 Columns 栅格。
HML(HarmonyOS Markup Language)是一套类 HTML 的标记语言,经过组件,事件构建出页面的内容。页面具有事件绑定、数据绑定、列表渲染、条件渲染和逻辑控制等能力。
hml 中事件绑定默认返回一个事件对象参数,能够经过该参数获取事件信息,同时也能够传递额外参数。
<!-- xxx.hml -->
<div>
<!-- 正常格式 -->
<div onclick="clickfunc"></div>
<!-- 缩写 -->
<div @click="clickfunc('hello')"></div>
<!-- 使用事件冒泡模式绑定事件回调函数 -->
<div on:touchstart.bubble="touchstartfunc"></div>
<!-- 使用事件捕获模式绑定事件回调函数 -->
<div on:touchstart.capture="touchstartfunc"></div>
<!-- on:{event}等价于on:{event}.bubble -->
<div on:touchstart="touchstartfunc"></div>
<!-- 绑定事件回调函数,但阻止事件向上传递 -->
<div grab:touchstart.bubble="touchstartfunc"></div>
<!-- 绑定事件回调函数,但阻止事件向下传递 -->
<div grab:touchstart.capture="touchstartfunc"></div>
<!-- grab:{event}等价于grab:{event}.bubble -->
<div grab:touchstart="touchstartfunc"></div>
</div>
复制代码
// xxx.js
export default {
data: {
text: '',
},
clickfunc: function(str, e) {
console.log(e);
this.text = str;
},
touchstartfunc: function(e) {
console.log(e);
}
}
复制代码
数据绑定的形式分两种:数据初始化,数据更新
hml 只支持数据层到视图层的单向数据绑定。 视图层想改变数据层,只能经过绑定事件的方式实现。
hml 中的数据都来自于对应 js 中的 data 对象,所以在初始化页面时,在 data 对象中写入数据,hml 中就能够经过 {{}} 的形式绑定数据。
// xxx.js
export default {
data: {
text: 'HELLO WORLD'
}
}
复制代码
<!-- xxx.hml -->
<div>{{text}}</div>
复制代码
经过为页面元素绑定事件,能够调用方法更新数据,从而触发视图更新数据
// xxx.js
export default {
data: {
text: 'HELLO WORLD'
},
changeText: function() {
this.$set('text', '你好,世界');
}
}
复制代码
<!-- xxx.hml -->
<div @click='changeText'>{{text}}</div>
复制代码
hml 中须要进行列表渲染的话只需在组件上添加 for 属性并绑定须要渲染的数据,同时可自定义变量和索引的名称:
// xxx.js
export default {
data: {
array: [
{id: 1, name: '老周', age: 28},
{id: 2, name: '老李', age: 29},
],
},
changeText: function(val, index) {
if (val === "老李"){
this.array.splice(index, 1, {id:2, name: '老王', age: 30});
} else {
this.array.splice(index, 1, {id:3, name: '老郑', age: 31});
}
},
}
复制代码
<!-- xxx.hml -->
<div class="array-container">
<!-- div列表渲染 -->
<!-- 默认$item表明数组中的元素, $idx表明数组中的元素索引 -->
<div for="{{array}}" tid="id" onclick="changeText($item.name, $idx)">
<text>{{$idx}}.{{$item.name}}</text>
</div>
<!-- 自定义元素变量名称 -->
<div for="{{value in array}}" tid="id" onclick="changeText(value.name, $idx)">
<text>{{$idx}}.{{value.name}}</text>
</div>
<!-- 自定义元素变量、索引名称 -->
<div for="{{(index, value) in array}}" tid="id" onclick="changeText(value.name, index)">
<text>{{index}}.{{value.name}}</text>
</div>
</div>
复制代码
数组中的每一个元素必须存在 tid 指定的数据属性,且必须具备惟一性。 针对数组内的数据修改,请使用 splice 方法生效数据绑定变动
hml 中实现条件渲染有两种方式,分别是为组件添加 if/elif/else 或 show 属性,它们的区别在于 if/elif/else 属性不符合条件判断则不会在 vdom 中构建,而 show 属性为 false 时虽然不会渲染,可是会在 vdom 中构建,只是设置了 display 样式为 none。
所以出于性能因素考虑,显示隐藏状态须要频繁切换推荐使用 show,显示状态改变次数较少则使用 if/elif/else。
// xxx.js
export default {
data: {
show: false,
display: true,
visible: false
},
toggle: function() {
this.visible = !this.visible;
}
}
复制代码
<!-- xxx.hml -->
<div class="container">
<text if="{{show}}"> 你好,世界 </text>
<text elif="{{display}}"> hi </text>
<text else> Hello World </text>
<button class="btn" type="capsule" value="toggle" onclick="toggle"></button>
<text show="{{visible}}" > Hello World! </text>
</div>
复制代码
当使用 if/elif/else 写法时,节点必须是兄弟节点,不然编译没法经过 禁止在同一个元素上同时设置 for 和 if 属性
hml 中提供了 控制块,它不会被看成真实的节点编译,可是只支持 for 和 if 属性。
HML 能够经过 element 标签引用模板文件,经过它能够实现自定义组件。
<!-- template.hml -->
<div class="item">
<text>Name: {{name}}</text>
<text>Age: {{age}}</text>
</div>
复制代码
<!-- index.hml -->
<element name='man' src='../../common/template.hml'></element>
<div>
<man name="老朱" age="28"></man>
</div>
复制代码
其中 element 标签的 name 属性则为自定义组件的名称,src 属性为自定义组件相对该文件的路径,能够为自定义组件标签添加属性向其传递数据,自定义组件内也可以使用 $emit
方法向父组件传递参数。
鸿蒙中的 js 文件支持 ES6 语法。
鸿蒙中可使用 import 方法引入功能模块或 js 代码:
import router from '@system.router'
import utils from '../../common/utils.js'
复制代码
在页面中可使用 this.$app.$def
获取在 app.js 中暴露的对象。
// app.js
export default {
onCreate() {
console.info('App onCreate');
},
onDestroy() {
console.info('App onDestroy');
},
globalData: {
appData: 'appData',
appVersion: '2.0',
},
changeAppVer () {
this.globalData.appVersion = '3.0';
}
};
复制代码
// index.js
export default {
data: {
appData: 'localData',
appVersion:'1.0',
},
onInit() {
this.appData = this.$app.$def.globalData.appData;
this.appVersion = this.$app.$def.globalData.appVersion;
},
pageMethod() {
this.$app.$def.changeAppVer();
}
}
复制代码
属性 | 类型 | 描述 |
---|---|---|
data | Object/Function | 页面的数据模型 |
$refs | Object | 持有注册过 ref 属性的 DOM 元素或子组件实例的对象 |
props | Array/Object | props 用于接收父组件传递过来的参数 |
computed | Object | 计算属性,用于在读取或设置进行预先处理,计算属性的结果会被缓存 |
private | Object | 页面的数据模型,private 下的数据属性只能由当前页面修改 |
public | Object | 页面的数据模型,public 下的数据属性的行为与 data 保持一致 |
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$set | Function | key: string, value: any | 添加新的数据属性或者修改已有数据属性。用法:this.$set('key',value)。 |
$delete | Function | key: string | 删除数据属性。用法:this.$delete('key')。 |
export default {
data: {
appInfo: {
OS: 'HarmonyOS',
Version: '2.0',
},
},
changeAppInfo() {
this.$set('appInfo.Version', '3.0');
console.log(this.appInfo);
this.$delete('appInfo');
console.log(this.appInfo);
}
}
复制代码
鸿蒙中可使用 $watch 方法观察 data 中的属性变化,若是属性值改变,则会触发绑定的事件。
export default {
props: ['title'],
onInit() {
this.$watch('title', 'onPropChange');
},
onPropChange(newV, oldV) {
console.info('title属性由'+ oldV +'变化为' + newV);
},
}
复制代码
{
"pages": [
"pages/index/index",
"pages/detail/index"
]
}
复制代码
鸿蒙 app 中页面的路由信息保存在 src > main > config.json 文件中的 pages 内,引入 @system.router 后,调用其 push 方法传入须要跳转页面的 uri,便可完成跳转,也可以使用其 back 方法回到首页。
import router from '@system.router';
export default {
launch() {
router.push ({
uri: 'pages/detail/index',
});
},
goBack() {
router.back();
}
}
复制代码
CSS 是描述 HML 页面结构的样式语言,全部组件均存在系统默认样式,也可在页面 CSS 样式文件中对组件、页面自定义不一样的样式。
鸿蒙中尺寸单位有两种,px(逻辑像素) 以及百分比。
{
"window": {
"designWidth": 720,
"autoDesignWidth": false
}
}
复制代码
逻辑像素的配置在 src > main > config.json 文件中的 window 内,designWidth 为屏幕的逻辑宽度,默认为720px,实际显示时会将页面布局缩放至屏幕实际宽度,如100px在实际宽度为1440物理像素的屏幕上,实际渲染为200物理像素。
当 autoDesignWidth 设置为 true 时,逻辑像素 px 将按照屏幕密度进行缩放,如 100px 在屏幕密度为3的设备上,实际渲染为300物理像素。
而百分比单位表示该组件占父组件尺寸的百分比,如组件的 width 设置为50%,表明其宽度为父组件的50%。
CSS 样式文件支持 @import 语句,导入 CSS 文件。
@import '../../common/style.css';
复制代码
使用鸿蒙的 JS SDK 开发 App,总体的项目结构、生命周期以及开发流程很像微信的小程序,而 hml 和 JS 的语法又很像 Vue,整个流程走下来,感受对 web 开发者而言仍是很友好的,相信有 Web 前端开发基础的小伙伴们均可以快速的上手。
因为篇幅有限,文中还有不少没有提到的鸿蒙赋予开发者的硬件调用能力,但愿鸿蒙能够越作越好,让愈来愈多的开发者和用户加入到鸿蒙的大生态中来。