This article appears in nuggets on June 7, 2021
Recommended articles:
TypeScript Utility Types, do you really understand TypeScript Utility Types?
TypeScript advancements, how to avoid any
So how do I start
Enter the official website of Hongmeng OS and download HUAWEI DevEco Studio
Then preview the downloaded zip directly and click on the executable
After a few seconds, this screen appears, clickNext >
Choose an installation path, not on the system disk
Perform some pre-installation initialization Settings, including adding shortcuts to the desktop, updating environment variables, and adding options to the right mouse button menu. Let’s select the first one first
The next step is to select the default directory for the project
When the installation is complete, click Finish and find the shortcut
Double-click to open it and click Agree
You need to configure the download source, the default value is huawei source, that does not care, the bottom right corner directly determine
The next step is to install SDK, path do not select system disk
Confirm the information
Agree, then wait a few minutes to download and install
Once the installation is complete, let’s create a project to try it out
Choose a template, choose which reference developer.harmonyos.com/cn/docs/doc… As a JavaScript siege lion, we’ll have to find a JS one. Choose this one
Configure the initial project information
After opening the project, press Alt + 3 to open the preview and get the following page
Let’s make a calculator
Simple requirements analysis
Let’s start with what huawei’s own calculator looks like
There’s a little bit more on the top right, and you can choose scientific notation and history, so we’re just going to do history here
In the middle is the input content and the calculation results of the display area
The bottom half is the button area for the calculator
Look at the document
Back to development tools, Harmony JS application directory structure see developer.harmonyos.com/cn/docs/doc…
A few files and folders to keep an eye on are
/ entry/SRC/main/js/default/app. Js for global JavaScript logic and application lifecycle management/entry/SRC/main/js/default/common to hold public resource files, such as: Media resources, custom components and JS files/entry/SRC/main/JS/default/pages used to hold all of the componentsCopy the code
Refer to the documentation for HML, CSS, and JS syntax
If you’ve ever developed applets or Vue applications, these are probably the only things you need to focus on
-
hml
- event
- The template reference
-
css
- Size of the unit
- Selectors (see how many there are) – pseudo classes
:waiting
- Style precompilation
-
js
- Look at all
Just start
Will the project/entry/SRC/main/js/default/pages/code does not need to delete in the index
Only this part is retained in 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>
Copy the code
We changed it slightly so that the calculator doesn’t need to display text at the top, just one more icon in the upper right corner
<div class="top-tool-bar">
<image
class="toolbar-more"
src="{{ images_resource.more }}"
@click="handleMore"
></image>
<! -- Delete text component -->
<! Alter image component class name -->
<! Change the image component binding event callback name, remember to change the js file function name.
<! -- Changed the attribute name of the binding image path images_resource to image_add -->
</div>
Copy the code
.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); /* Add background color definition */
}
.top-tool-bar {
display: flex;
flex-direction: row;
justify-content: flex-end; /* Add this line */
align-items: center;
width: 100%;
height: 56px;
padding-left: 24px;
padding-right: 24px;
}
.toolbar-more {
/* Changed the selector name to tool-image1 */
width: 24px;
height: 24px;
margin-left: 16px; /* left */
opacity: 0.9;
}
Copy the code
We cut out the picture of Huawei calculator above, use PhotoShop to keep the icon in the upper right corner, make the background color transparent, and cut the size to 48 * 48 (the figure below is 96).
Use the Input component to reserve two places for the numeric display area and the result area
The data is then created to render the keyboard area
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,
},
},
};
Copy the code
HML body area
<! -- Top, add custom components -->
<element src="./components/keyboard-button/keyboard-button.hml" name="keyboard-button">
</element>
<! -- Body area, render the list according to the values defined above -->
<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>
Copy the code
CSS new
.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;
}
Copy the code
It does not support dynamically binding classes, which can be difficult to implement if the layout is very complex, and Flex’s layout does not behave the same as Chrome’s, so it is better to define the width and height directly
Keyboard – Button is a custom component THAT I added to deal with the fact that it doesn’t support dynamic classes
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>
Copy the code
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;
}
Copy the code
keyboard-button.js
export default {
props: ["type"."typeDict"."text"]};Copy the code
The final preview looks like this
Try the system capability, click the button long vibration, since we are a custom component, we need to trigger a custom event
In the keyboard-button component, trigger the custom event click with the parameter this.text
this.$emit("click".this.text);
Copy the code
index.hml
<keyboard-button @click="handleClick"></keyboard-button>
Copy the code
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}`); }}); }};Copy the code
Real machine test
On the real machine test effect, how to on the real machine, first take the data line to connect the phone to the computer, the phone to open the developer mode, open THE USB debugging, choose to transfer files
We can see this document after developer.harmonyos.com/cn/docs/doc…
After the app was installed on the real machine, there was no vibration when I clicked the button. After checking the document, I found that such a clause should be added in config.json
{
"reqPermissions": [{"name": "ohos.permission.VIBRATE"."reason": ""."usedScene": {
"ability": [".MainAbility"]."when": "inuse"}}}]Copy the code
After compiling and running, click the button can vibrate!
#The sample code
https://github.com/kawayiLinLin/harmony-calculator
Copy the code
Why don’t we meet next time on HarmonyOS: How to Make a Great App, Part 1
Let’s go for the college entrance examination
Original text: yzl. Xyz/Lin / 2021/06…