本文于2021年6月7日在掘金发布
推荐文章:
怎么开始呢
进入鸿蒙 OS 官网,下载 HUAWEI DevEco Studio
之后直接预览下载的压缩包,并点击这个可执行文件
等待几秒后,出现这样的界面,点 Next >
选择一个安装路径,不要安装在系统盘哦
进行一些安装前的初始化设置,依次是桌面添加快捷方式,更新环境变量,鼠标右键菜单增加选项,我们先只选第一个
下一步是选择项目的默认目录,没什么用,直接 Install
安装完成后,点 Finish
,然后找到快捷方式
双击打开,点击 Agree
弹出提示,看到了熟悉的 npm
,大意就是这个开发工具需要 npm
,你要配置下载源,默认值给的是华为源,那不用管,右下角直接确定
下一步是装 SDK,路径不要选系统盘
确认一下信息
同意,然后等待几分钟下载安装
安装完成后,我们创建一个项目试一下
选择一个模板,选哪个参考 developer.harmonyos.com/cn/docs/doc…,作为一个 JavaScript 攻城狮,那我们肯定找个 JS 的,选这个吧
配置下项目初始信息
打开项目后,按下 Alt + 3
,打开预览,得到如下的页面
动手做一个计算器吧
简单的需求分析
首先看看华为自带的计算器长啥样吧
右上角有一个更多了,可以选择科学计数法和历史记录,这里我们只做历史记录
中间是输入内容以及计算结果的显示区域
下半部分是计算器的按钮区域
看看文档
回到开发工具中,Harmony JS 应用的目录结构见 developer.harmonyos.com/cn/docs/doc…
需要关注的几个文件和文件夹就是
/entry/src/main/js/default/app.js 用于全局JavaScript逻辑和应用生命周期管理
/entry/src/main/js/default/common 用于存放公共资源文件,比如:媒体资源,自定义组件和JS文件
/entry/src/main/js/default/pages 用于存放所有组件页面
关于 HML
、 CSS
和 JS
语法请参考文档
如果你开发过小程序或者 vue 应用,那你可能只需要关注下这几点
-
hml
- 事件绑定
- 模板引用
-
css
- 尺寸单位
- 选择器(看看一共有几个)-伪类
:waiting
- 样式预编译
-
js
- 全部都看
直接开始
将项目中的 /entry/src/main/js/default/pages/index 中不需要的代码删除
hml 中只保留这部分
<div class="container">
<!-- top tool bar -->
<div class="top-tool-bar">
<image
class="toolbar-image1"
src="{{ images_resource.image_add }}"
@click="backHome"
></image>
<text class="title"> {{ $t('strings.title') }} </text>
</div>
<!-- body -->
</div>
我们稍作改动,计算器最上边不需要显示文字,只有右上角显示一个更多的图标
<div class="top-tool-bar">
<image
class="toolbar-more"
src="{{ images_resource.more }}"
@click="handleMore"
></image>
<!-- 删除了 text 组件 -->
<!-- 修改了 image 组件类名 -->
<!-- 修改了 image 组件绑定事件回调名,记得同步修改 js 文件中的函数名 -->
<!-- 修改了绑定图片路径 images_resource 的属性名,原为 image_add -->
</div>
.container {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
width: 100%;
left: 0px;
top: 0px;
background-color: rgb(233, 236, 241); /* 增加背景色定义 */
}
.top-tool-bar {
display: flex;
flex-direction: row;
justify-content: flex-end; /* 增加这一行 */
align-items: center;
width: 100%;
height: 56px;
padding-left: 24px;
padding-right: 24px;
}
.toolbar-more {
/* 修改了选择器名,原为 toolbar-image1 */
width: 24px;
height: 24px;
margin-left: 16px; /* right 改为 left */
opacity: 0.9;
}
我们裁剪下上面那张华为计算器的图,使用 PhotoShop 保留右上角的图标,并将其底色置为透明,尺寸裁剪为 48 * 48 (下图为 96)
使用 input 组件给数值展示区域和结果区域预留两个位置
接下来造数据用于渲染键盘区域
const typeDict = {
other: "other",
number: "number",
operator: "operator",
confirm: "confirm",
};
export default {
data: {
typeDict,
keyboardItemsNormal: [
[
{
keyName: "MC",
id: 1,
type: typeDict.other,
},
// ....
],
[
// ....
{
keyName: "⇐",
id: 8,
type: typeDict.other,
},
],
[
// ....
{
keyName: "-",
id: 12,
type: typeDict.operator,
},
],
[
// ....
{
keyName: "+",
id: 16,
type: typeDict.operator,
},
],
],
keyboardItemsLastTwoLine: [
[
// ....
{
keyName: "3",
id: 19,
type: typeDict.number,
},
],
[
// ....
{
keyName: ".",
id: 23,
type: typeDict.number,
},
],
],
keyboardItemConfirm: {
keyName: "=",
id: 20,
type: typeDict.confirm,
},
},
};
hml body 区域
<!-- 最上方,加入了自定义组件 -->
<element src="./components/keyboard-button/keyboard-button.hml" name="keyboard-button">
</element>
<!-- body 区域,依照前文定义的值进行列表渲染 -->
<div class="result">
<input class="expression-input" value="1+2"></input>
<input class="result-input" value="3"></input>
</div>
<div class="keyboard">
<block for="{{ (index, row) in keyboardItemsNormal }}">
<div tid="{{ index }}" class="keyboard-row">
<block for="{{ (rowIndex, item) in row }}">
<div tid="{{ item.id }}" class="keyboard-item">
<keyboard-button type="{{ item.type }}" text="{{ item.keyName }}" type-dict="{{ typeDict }}">
</keyboard-button>
</div>
</block>
</div>
</block>
<div class="keyboard-row-last">
<div class="keyboard-row-last-left">
<block for="{{ (index, row) in keyboardItemsLastTwoLine }}">
<div tid="{{ item.id }}" class="keyboard-row">
<block for="{{ (rowIndex, item) in row }}">
<div tid="item.id" class="keyboard-item" style="width: 200px;">
<keyboard-button type="{{ item.type }}" text="{{ item.keyName }}" type-dict="{{ typeDict }}">
</keyboard-button>
</div>
</block>
</div>
</block>
</div>
<div class="keyboard-row-last-right">
<keyboard-button type="{{ keyboardItemConfirm.type }}" text="{{ keyboardItemConfirm.keyName }}" type-dict="{{ typeDict }}">
</keyboard-button>
</div>
</div>
</div>
css 新增
.result {
display: flex;
flex-direction: column;
}
.result input {
background-color: transparent;
}
.result .expression-input {
height: 60px;
font-size: 30px;
font-weight: bold;
}
.keyboard {
flex-grow: 1;
width: 100%;
display: flex;
flex-direction: column;
}
.keyboard .keyboard-row {
display: flex;
flex-wrap: nowrap;
align-items: center;
min-height: 100px;
}
.keyboard .keyboard-row .keyboard-item {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
position: relative;
}
.keyboard-row-last {
display: flex;
flex: 1;
flex-direction: row;
}
.keyboard-row-last .keyboard-row-last-left {
display: flex;
width: 75%;
flex-direction: column;
}
.keyboard-row-last .keyboard-row {
max-height: 100px;
}
它不支持动态绑定 class,如果布局非常复杂就会很难实现,flex 布局表现也和 chrome 不一致,感觉直接用宽高进行定义比较好
keyboard-button 是我添加的自定义组件,为了应付它不支持动态 class 的问题
keyboard-button.hml
<div>
<button type="circle" class="other" if="{{ type === typeDict.other }}">
{{ text }}
</button>
<button type="circle" class="number" elif="{{ type === typeDict.number }}">
{{ text }}
</button>
<button
type="circle"
class="operator"
elif="{{ type === typeDict.operator }}"
>
{{ text }}
</button>
<button class="confirm" elif="{{ type === typeDict.confirm }}">
{{ text }}
</button>
</div>
keyboard-button.css
button {
height: 65px;
font-size: 25px;
font-weight: bold;
}
.other {
font-weight: normal;
font-size: 18px;
text-color: #333333;
background-color: #ffffff;
}
.operator {
text-color: rgb(59, 110, 209);
background-color: #fff;
font-size: 30px;
}
.confirm {
height: 170px;
width: 60px;
border-radius: 30px;
margin-left: 20px;
margin-top: 15px;
}
keyboard-button.js
export default {
props: ["type", "typeDict", "text"],
};
最后的预览图长这个样子
试一下系统能力,点击按钮长震动,由于我们是自定义组件,所以需要触发自定义事件
在 keyboard-button 组件中,触发自定义事件 click,参数为 this.text
this.$emit("click", this.text);
index.hml
<keyboard-button @click="handleClick"></keyboard-button>
index.js
import vibrator from "@system.vibrator";
export default {
// ...
handleClick(event) {
vibrator.vibrate({
mode: "long",
success() {
console.log("success to vibrate");
},
fail(data, code) {
console.log(`handle fail, data = ${data}, code = ${code}`);
},
});
},
};
真机试验
上真机试验效果,怎么上真机呢,先拿数据线把手机连接上电脑,手机打开 开发者模式,打开 USB 调试,选择传输文件
之后可以看这篇文档 developer.harmonyos.com/cn/docs/doc…
真机安装上 app 后,点击按钮并没有震动,查文档发现需要在 config.json
里加入这样一条
{
"reqPermissions": [
{
"name": "ohos.permission.VIBRATE",
"reason": "",
"usedScene": {
"ability": [".MainAbility"],
"when": "inuse"
}
}
]
}
之后再编译运行,点击按钮就可以震动了!
# 示例代码
https://github.com/kawayiLinLin/harmony-calculator
下次让我们在 “HarmonyOS 来了,如何开发一个鸿蒙应用,上篇” 相遇吧
大家高考加油,金榜题名