鸿蒙待办事项应用【鸿蒙专题14】

举报
坚果的博客 发表于 2022/02/17 08:11:02 2022/02/17
【摘要】 作者:坚果公众号:"大前端之旅"华为云享专家,InfoQ签约作者,阿里云专家博主,51CTO博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。在前几篇文章里也介绍了许多关于鸿蒙开发的技巧,今天我们就来做自己的第一个代办事项应用。鸿蒙开发和Flutter一样,都具有跨平台的特性,Flutter一套代码可以在Andro...



作者:坚果

公众号:"大前端之旅"

华为云享专家,InfoQ签约作者,阿里云专家博主,51CTO博客首席体验官,开源项目GVA成员之一,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。

在前几篇文章里也介绍了许多关于鸿蒙开发的技巧,今天我们就来做自己的第一个代办事项应用。鸿蒙开发和Flutter一样,都具有跨平台的特性,Flutter一套代码可以在Android,ios,web。linux,desk等部署,鸿蒙也有这样的特性,可同时在手机、大屏、手表生效,体验“一次开发、多设备部署”特性。

接下来我们开始正文

第一步必然是安装 DevEco Studio 。推荐安装3.0beta版,学习的话,用3.0还是蛮不错的。

第二部新建工程

自从微信小程序出现以来,各种“小程序”如雨后春笋一般出现。事实证明小程序这种开发方式非常好,鸿蒙 JS UI 框架采用类似的方式也是在意料之中的。

一个小程序(在鸿蒙 OS 中,也就是 Ability)由多个页面组成,每个页面由三部分组成:

  • .hml 用来描述界面的元素

  • .css 用来描述界面的风格

  • .js 用来编写处理事件逻辑

我们来看个例子:



js文件

const BUTTON_STATE_IMAGE = ["/common/checkbutton.png", "/common/done.png"];
const TAG_STATE = ["show", "hide"];
const TEXT_COLOR = ["text-default", "text-gray"];
const EVENT_LEVEL = ["urgent", "senior", "middle", "low"];
export default {
    title: "任务列表",
    taskList: [
        {
            id: "id-1",
            event: "购买礼物",
            time: "10:30",
            checkBtn: BUTTON_STATE_IMAGE[1],
            color: TEXT_COLOR[1],
            showTag: TAG_STATE[1],
            tag: EVENT_LEVEL[1],
        },
        {
            id: "id-2",
            event: "健身锻炼",
            time: "15:30",
            checkBtn: BUTTON_STATE_IMAGE[0],
            color: TEXT_COLOR[0],
            showTag: TAG_STATE[0],
            tag: EVENT_LEVEL[0],
        },
        {
            id: "id-3",
            event: "生日约会",
            time: "19:30",
            checkBtn: BUTTON_STATE_IMAGE[0],
            color: TEXT_COLOR[0],
            showTag: TAG_STATE[0],
            tag: EVENT_LEVEL[2],
        },
    ]
};

css文件

.container {
    flex-direction: column;
    background-color: black;
}
.title {
    font-weight: 600;
    color: #ccc;
    background-color: black;
    opacity: 1;
}
.tag-list {
    width: 100%;
}
.todo-list-item {
    width: 100%;
}
.todo-item {
    width: 100%;
    border-radius: 2px;
    align-items: center;
}
.flex-row {
    display: flex;
    flex-direction: row;
    align-items: center;
}
.todo-name-mark {
    width: 100%;
    height: 100%;
    align-items: center;
}
.todo-name {
    font-size: 16px;
    color: white;
    margin-right: 2px;
    max-lines: 1;
    text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
    display: inline-block;
    vertical-align: middle;
}
.text-default {
    color: white;
}
.text-gray {
    color: gray;
}
.todo-mark {
    width: 9px;
    height: 9px;
    margin-left: 8px;
    border-radius: 25px;
    background-color: lightslategrey;
}
.todo-time {
    font-size: 14px;
    width: 100%;
    height: 100%;
    text-align: left;
    color: gray;
    margin-top:1px;
}
.urgent {
    background-color: firebrick;
}
.senior {
    background-color: gold;
}
.middle {
    background-color: mediumaquamarine;
}
.low {
    background-color: #0D9FFB;
}
.hide {
    display: none;
}
.show {
    display: inline-block;
}
.todo-image {
    width: 20px;
    height: 20px;
    object-fit: contain;
    margin-top: 1px;
}
.todo-text-wrapper {
    height: 100%;
    flex-grow: 1;
    margin: 0px 16px;
    flex-direction: column;
}
@media (device-type: tv) {
    .title {
        font-size: 22px;
        padding: 10px;
    }
    .tag-list {
        padding-top:30px;
        padding-left:12px;
    }
    .todo-list-item {
        margin-top: 20px;
    }
    .todo-image {
        width: 20px;
        height: 20px;
    }
    .todo-name {
        font-size: 18px;
        max-width: 460px
    }
}
@media (device-type: phone) {
    .title {
        font-size: 21px;
        padding-top: 10px;
        padding-bottom: 10px;
        padding-left: 10px;
    }
    .tag-list {
        padding-top:48px;
    }
    .todo-list-item {
        margin: 2px 8px;
    }
    .todo-name-mark {
        margin: 5px 0px;
    }
    .todo-name {
        max-width: 180px;
    }
}
@media (device-type: wearable) {
    .title {
        font-size: 26px;
        width: 100%;
        height: 54px;
        text-align: center;
    }
    .tag-list {
        padding-top:54px;
    }
    .todo-list-item {
        padding-left: 50px;
        padding-right: 25px;
    }
    .todo-name-mark {
        margin: 3px 0px;
    }
    .todo-name {
        max-width: 106px
    }
}

htm文件

<div class="container">
    <text class="title">
        {{title}}
    </text>
    <list class="tag-list">
        <list-item for="{{taskList}}" class="todo-list-item" focusable="false">
            <div class="todo-item flex-row">
                <image class="todo-image" src="{{$item.checkBtn}}" onclick="completeEvent({{$item.id}})"></image>
                <div class="todo-text-wrapper">
                    <div class="todo-name-mark">
                        <text class="todo-name {{$item.color}}" focusable="false">{{$item.event}}</text>
                        <text class="todo-mark {{$item.tag}} {{$item.showTag}}"></text>
                    </div>
                    <text class="todo-time">{{$item.time}}</text>
                </div>
            </div>
        </list-item>
    </list>
</div>


2. 工作原理

要理解它的工作原理,先研究一下编译之后的代码是非常重要的。上面的三个文件,编译之后会生成一个文件,其位置在:./entry/build/intermediates/res/debug/lite/assets/js/default/pages/index/index.js

index.hml 变成了创建函数:


index.css 变成了 JSON 文件。

这种处理方式很妙,把 JS 不擅长处理的 XML/CSS 转换成了 JS 代码和 JSON 对象,这个转换由工具完成,避免了运行时的开销。

在没有研究编译之后的代码时,我尝试在 ace/graphic 两个包中寻找解析 HML 的代码,让我惊讶的是没有找到相关代码。看了这些生成的代码之后才恍然大悟。


计数器应用:

index.hml

<div class="container">
    <text>{{count}}</text>
    <input if="{{count < 10}}"type="button" value="Inc" onclick="inc"/>
    <input if="{{count > 0}}" type="button" value="Dec" onclick="dec"/>
</div>

index.css

.container {
    flex-direction: column;
    justify-content: center;
    align-items: center;
    left: 0px;
    top: 0px;
    width: 454px;
    height: 454px;
}

index.js

export default {
    data: {
        count: 5
    },
​
    inc() {
        this.count++;
    },
​
    dec() {
        this.count--;
    }
}

参考文档

https://my.oschina.net/u/3979680/blog/4613811?_from=gitee_search

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。