当前位置:   article > 正文

鸿蒙应用开发初试_鸿蒙小程序开发

鸿蒙小程序开发

一、简介

  • 鸿蒙 (HarmonyOS) 是一款由华为开发的,面向全场景的分布式操作系统。其开源项目为 OpenHarmony。
  • 超级小程序
    • H5 -> 小程序 -> 超级小程序
  • 可剪裁系统
    • 128 KB – 128 MB – 4 GB
  • 模改通讯协议
    • 类似普通话,统一了方言。鸿蒙成为 IoT 互联互通的标准语言

发布会现场

在这里插入图片描述

二、储备知识

  • 熟悉前端技术栈(HTML、CSS、JS)
    • 类 Web 范式编程(鸿蒙开发不是浏览器环境)
    • 例如:鸿蒙中的 div 是自己封装的,不是 Web 端的 div
  • 熟悉微信小程序
    • 页面结构、API、配置方式
  • 熟悉 Vue 2
    • 鸿蒙自己实现的类 Vue 2 的 MVVM 模式(观察者模式,数据劫持)
  • 有安卓开发经验更好

在这里插入图片描述

三、鸿蒙系统架构

在这里插入图片描述
鸿蒙系统架构

  • 应用层
    • 鸿蒙的应用由一个或多个 FA(Feature Ability)或 PA(Particle Ability)组成
    • FA 有 UI 界面,提供与用户交互的能力;而 PA 无 UI 界面,提供后台运行任务的能力
  • 框架层
    • 提供了 Java/C/C++/JS 等用户程序框架和 Ability 框架
    • 两种 UI 框架(Java UI 框架、JS UI 框架)
  • 系统服务层
    • 系统服务层是鸿蒙的核心能力集合,通过框架层对应用程序提供服务
  • 内核层
    • 采用多内核设计,支持针对不同资源受限设备,选用适合的 OS 内核

对Ability(能力)的解释

在这里插入图片描述

在这里插入图片描述

四、鸿蒙是不是安卓套壳

我们对比一下鸿蒙和安卓的架构

安卓系统
在这里插入图片描述
鸿蒙系统
在这里插入图片描述

对比

在这里插入图片描述

五、鸿蒙应用开发

在线体验:https://playground.harmonyos.com/

开发环境搭建(DevEco Studio)

鸿蒙js

在这里插入图片描述

  • 应用层
    • 开发者使用 JS UI 框架开发的 FA 应用
  • 前端框架层
    • 完成前端页面解析,提供 MVVM 开发模式、页面路由和自定义组件等能力
  • 引擎层
    • 完成动画解析、DOM 树构建、布局计算、渲染命令构建与绘制、事件管理等
  • 适配层
    • 完成对平台层的对接,比如:事件对接、渲染管线对接和系统生命周期对接等

在这里插入图片描述

  • JS Data binding
    • JS 数据绑定框架使用 JavaScript 语言提供一套基础的数据绑定能力。
  • JS runtime
    • 支持 JS 代码的解析和执行。
  • JS Runtime 的解析引擎为 JerryScript
    • JS framework
    • JS 框架部分使用 C++ 语言实现,提供 JS API 和组件的框架机制。

https://jerryscript.net/

在这里插入图片描述

JS 原生(NAPI)

在这里插入图片描述

  • NativeEngine
    • JS 引擎抽象层,统一 JS 引擎在 NAPI 层的接口行为。
  • ModuleManager
    • 管理模块,用于模块加载、模块信息缓存。
  • ScopeManager
    • 管理 NativeValue 的生命周期。
  • ReferenceManager
    • 管理 NativeReference 的生命周期。

https://github.com/quickjs-zh/QuickJS

在这里插入图片描述

六、案例

目录结构

在这里插入图片描述
html

<element name="fragment_main" src="../../common/fragment_main/fragment_main.hml"></element>

<div class="container">

<!-- top tool bar   -->
    <div class="top-tool-bar">
        <image class="toolbar-image1" src="{{ images_resource.image_add }}" onclick="onClick"></image>
        <image class="toolbar-image2" src="{{ images_resource.image_add }}" onclick="onClick"></image>
        <image class="toolbar-image3" src="{{ images_resource.image_more }}" onclick="onClick2"></image>
    </div>

<!--bottom tool Bar-->
    <tabs class="tabs" index="0" vertical="false" onchange="change">
        <tab-bar class="bottomBar-wrapper" mode="fixed">
            <div class="bottomBar-item-wrapper">
                <image class="bottomBarItem-image" src="{{ images_resource.image_icon }}"></image>
                <text class="bottomBarItem-text">{{ $t('strings.tab_name') }}</text>
            </div>
            <div class="bottomBar-item-wrapper">
                <image class="bottomBarItem-image" src="{{ images_resource.image_icon }}"></image>
                <text class="bottomBarItem-text">{{ $t('strings.tab_name') }}</text>
            </div>
            <div class="bottomBar-item-wrapper">
                <image class="bottomBarItem-image" src="{{ images_resource.image_icon }}"></image>
                <text class="bottomBarItem-text">{{ $t('strings.tab_name') }}</text>
            </div>
            <div class="bottomBar-item-wrapper">
                <image class="bottomBarItem-image" src="{{ images_resource.image_icon }}"></image>
                <text class="bottomBarItem-text">{{ $t('strings.tab_name') }}</text>
            </div>
            <div class="bottomBar-item-wrapper">
                <image class="bottomBarItem-image" src="{{ images_resource.image_icon }}"></image>
                <text class="bottomBarItem-text">{{ $t('strings.tab_name') }}</text>
            </div>
        </tab-bar>

        <tab-content class="tabContent" scrollable="true">
            <div class="item-content">
                <fragment_main></fragment_main>
            </div>
            <div class="item-content">
                <text class="item-title">{{ $t('strings.second_page') }}</text>
            </div>
            <div class="item-content">
                <text class="item-title">{{ $t('strings.third_page') }}</text>
            </div>
            <div class="item-content">
                <text class="item-title">{{ $t('strings.fourth_page') }}</text>
            </div>
            <div class="item-content">
                <text class="item-title">{{ $t('strings.fifth_page') }}</text>
            </div>
        </tab-content>
    </tabs>

    <div class="fragment_main_wearable">
        <fragment_main id="id_fragment_main"></fragment_main>
    </div>

</div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

js

import prompt from '@system.prompt';
import device from '@system.device';
import mediaquery from '@system.mediaquery';

const TAG = '[index]';
var mMediaQueryList;
var context;

// js call java
// abilityType: 0-Ability; 1-Internal Ability
const ABILITY_TYPE_EXTERNAL = 0;
const ABILITY_TYPE_INTERNAL = 1;
// syncOption(Optional, default sync): 0-Sync; 1-Async
const ACTION_SYNC = 0;
const ACTION_ASYNC = 1;
const ACTION_MESSAGE_CODE = 1001;
var wearableMediaListener = function (e) {
    if (e.matches) {
        // do something
        console.log(TAG + "Success Media Listen");
        context.initial_value = 4;
        context.$child('id_fragment_main').initial_index_value = 0;
        context.$child('id_fragment_main').list_data.forEach(element => {
            element.item_icon = context.images_resource_dark_mode.image_icon;
            element.item_right_arrow = context.images_resource_dark_mode.image_right_arrow;
        });
    }
};
var getDeviceInfo = function () {
    var res = '';
    device.getInfo({
        success: function (data) {
            console.log(TAG + 'Success device obtained. screenShape=' + data.screenShape);
            this.res = data.screenShape;
        },
        fail: function (data, code) {
            console.log(TAG + 'Failed to obtain device. Error code=' + code + '; Error information: ' + data);
        },
    });
    return res;
};

export default {
    data: {
        images_resource: {
            "image_icon": "common/images/ic.png",
            "image_add": "common/images/add64.png",
            "image_more": "common/images/more.png",
            "image_right_arrow": "common/images/right_arrow.png"
        },
        images_resource_dark_mode: {
            "image_icon": "common/images/ic_dark_mode.png",
            "image_add": "common/images/add64.svg",
            "image_more": "common/images/more.svg",
            "image_right_arrow": "common/images/right_arrow_dark_mode.png"
        },
        initial_value: 0
    },
    onInit() {
        console.log(TAG + 'onInit');
        context = this;
        this.mMediaQueryList = mediaquery.matchMedia("screen and (device-type: wearable)");
        this.mMediaQueryList.addListener(wearableMediaListener);
        console.info(TAG + "java js" + this.getSystemColorModeByJava()); // async call and return null
    },
    onReady()
    {
        console.log(TAG + 'onReady');
        console.log(TAG + getDeviceInfo()); // getDeviceInfo after Init
    },
    onShow()
    {
        console.log(TAG + 'onShow');
    },
    onDestroy() {
        console.log(TAG + 'onDestroy');
        mMediaQueryList.removeListener(wearableMediaListener);
    },
    onClick() {
        prompt.showToast({
            message: "add",
            duration: 3000,
        });
    },
    onClick2() {
        prompt.showToast({
            message: "more",
            duration: 3000,
        });
    },
    getSystemColorModeByJava: async function() {
        var actionData = {};
        actionData.firstNum = 123;
        actionData.secondNum = 465;

        var action = {};
        action.bundleName = 'com.example.myapplication';
        action.abilityName = 'com.example.myapplication.ServiceAbilityForJS';
        action.messageCode = ACTION_MESSAGE_CODE;
        action.data = actionData;
        action.abilityType = ABILITY_TYPE_EXTERNAL;
        action.syncOption = ACTION_SYNC;

        var result = await FeatureAbility.callAbility(action);
        var ret = JSON.parse(result);
        if (ret.code == 0) {
            console.info('result is:' + JSON.stringify(ret.abilityResult));
        } else {
            console.error('error code:' + JSON.stringify(ret.code));
        }

        if (ret.getColorMode == 0) {
            console.info(TAG + ret.getColorMode);
            // get system color mode and do something
            this.images_resource = this.images_resource_dark_mode;
        }

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119

css

.container {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
    width: 100%;
    left: 0px;
    top: 0px;
}

.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-image1 {
    width: 24px;
    height: 24px;
    margin-right: 40px;
    opacity: 0.9;
}

.toolbar-image2 {
    width: 24px;
    height: 24px;
    margin-right: 40px;
    opacity: 0.9;
}

.toolbar-image3 {
    width: 24px;
    height: 24px;
    opacity: 0.9;
}

.tabs {
    width: 100%;
}

.bottomBar-wrapper {
    width: 100%;
    height: 56px;
    flex-direction: row;
    justify-content: flex-start;
    align-items: center;
    position: fixed;
    bottom: 0px;
}

.bottomBar-item-wrapper {
    width: 100%;
    height: 100%;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    margin-top: 0px;
    margin-bottom: 8px;
}

.bottomBarItem-image {
    height: 24px;
    width: 24px;
}

.bottomBarItem-text {
    font-size: 14px;
    opacity: 0.9;
    margin-top: 2px;
}

.tabContent {
    width: 100%;
    padding-bottom: 56px;
}

.item-content {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: flex-start;
    width: 100%;
}

.item-title {
    width: 100%;
    height: 100%;
    font-size: 18px;
    text-align: center;
}

/* wearable */

@media screen and (device-type: wearable) {
    .top-tool-bar {
        display: none;
    }

    .bottomBar-wrapper {
        display: none;
    }

}

/* phone */

@media screen and (device-type: phone) {
    .fragment_main_wearable {
        display: none;
    }
}

/* tablet */

@media screen and (device-type: tablet) {
    .fragment_main_wearable {
        display: none;
    }
}

/* tv */

@media screen and (device-type: tv) {
    .fragment_main_wearable {
        display: none;
    }

    .item-title {
        color: black;
    }

    .top-tool-bar {
        display: none;
    }

    .bottomBar-wrapper {
        display: none;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144

运行结果

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/252824
推荐阅读
相关标签
  

闽ICP备14008679号