This article appears in nuggets on June 7, 2021

Recommended articles:

  1. TypeScript Utility Types, do you really understand TypeScript Utility Types?

  2. 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…