• HarmonyOS开发(三):ArkTS基础


    1、ArkTS演进

    Mozilla创建了JS    --->    Microsoft创建了TS    ---->    Huawei进一步推出ArkTS

    从最初的基础逻辑交互(JS),到具备类型系统的高效工程开发(TS),再到融合声明式UI、多维状态管理等丰富的应用开发能力(ArkTS),共同组成了相关的演进脉络。

    ArkTS是HarmonyOS推荐开发语言。它在TypeScript的基础之上,扩展了声明式UI、状态管理等相应的能力,让开发者可以以更简洁、更自然的方式开发高性能应用。

    1.1、JS

    JS语言由Mozilla创造,最初主要是为了解决页面中的逻辑交互问题,它和HTML(负责页面内容)、CSS(负责页面布局和样式)共同组成了Web页面/应用开发的基础。随着Web和浏览器的普及,以及Node.js进一步将JS扩展到了浏览器以外的环境,JS语言得到了飞速的发展。在2015年相关的标准组织ECMA发布了一个主要的版本ECMAScript 6(简称ES6),这个版本具备了较为完整的语言能力,包括类(Class)、模块(Module)、相关的语言基础API增强(Map/Set等)、箭头函数(Arrow Function)等。从2015年开始,ECMA每年都会发布一个标准版本,比如ES2016/ES2017/ES2018等,JS语言越来越成熟。

    为了提升应用的开发效率,相应的JS前端框架也不断地涌现出来。其中比较典型的有Facebook发起的React.js,以及个人开发者尤雨溪发起的Vue.js。React和Vue的主要出发点都是将响应式编程的能力引入到应用开发中,实现数据和界面内容的自动关联处理。具体的实现方式上,React对JS做了一些扩展,引入了JSX(JavaScript XML)语法,可以将HTML的内容统一表示成JS来处理;Vue则是通过扩展的模板语法(Template)的方式来处理。

    1.2、TS

    Microsoft在JS的基础上,创建了TS语言,并在2014年正式发布了1.0版本。TS主要从以下几个方面做了进一步的增强。

    • 引入了类型系统,并提供了类型检查以及类型自动推导能力,可以进行编译时错误检查,有效的提升了代码的规范性以及错误检测范围和效率。
    • 在类型系统基础上,引入了声明文件(Declaration Files)来管理接口或其他自定义类型。声明文件一般是以d.ts的形式来定义模块中的接口,这些接口和具体的实现做了相应的分离,有助于各模块之间的分工协作。

    1.3、ArkTS

    基于JS前端框架及TS的引入,进一步提升了应用的开发效率,但是还是存在一些不足,这些不足的地方主要在如下两个方面体现:

    1. 从开发者纬度来看
      1. 写一个应用需要了解三种语言(JS/TS,HTML,CSS),对于开发者不够友好
    2. 从运行时维度来看
      1. TS虽然有类型的加持,但也仅限于编译时检查,然后通过TS Complier转成JS,运行时引擎还是无法利用到基于类型系统的优化
      2. 在渲染方面,主流web引擎与常见OS原生框架都有一定的差距,尤其在移动平台上。

    ArkUI开发框架整理体架构图:

    上图中,基于TS扩展的声明式UI范式中所用的语言就是ArkTS。

    ArkTS声明式开发范式代码示例

    1. @Entry
    2. @Component
    3. strcut Hello {
    4. @State myText: string = 'World'
    5. build() {
    6. Column() {
    7. Text('Hello')
    8. .fontSize(50)
    9. Text(this.myText)
    10. .fontSize(50)
    11. Divider()
    12. Button() {
    13. Text('点击我')
    14. .fontSize(30)
    15. }
    16. .onClick(() => {
    17. this.myText = 'ArkUI'
    18. })
    19. .width(200)
    20. .height(50)
    21. }
    22. }
    23. }

    上面示例代码说明:

    装饰器

    用来装饰类、结构体、方法以及变量,赋予其特殊含义,上面的@Entry、@Component、@State都是装饰器。

    @Component:表示这是一个自定义组件

    @Entry:表示是一个入口组件

    @State:表示是一个状态变量,这个变量的变化会引起UI的同步刷新

    自定义组件

    可复用的UI单元,可以组合其它的组件,如上面被@Component装饰的struct Hello

    UI描述

    声明式的方式来描述UI结构,如上面示例代码中build()方法内部代码

    内置组件

    框架中默认内置的基础和布局组件,可直接被开发者调用,比如示例中的 Column、Text、Divider、Button。

    事件方法

    用于添加组件对事件的响应逻辑,统一通过事件方法进行设置,如跟随在Button后面的onClick()。

    属性方法

    用于组件属性的配置,统一通过属性方法进行设置,如fontSize()、width()、height()、color() 等,可通过链式调用的方式设置多项属性。

    2、案例学习

    1、在DevEco Studio中新建一个Empty Ability项目:StudyList

    2、将选中和未选中两个图片资源放在:entry/src/main/resources/base/media中

    3、在entry/src/main/ets下新增目录:view

    4、在第3点中新增的目录下新增ets文件TitleComponent.ets

    1. @Component
    2. export struct TitleComponent {
    3. title: string = '学习列表'
    4. build() {
    5. Row(){
    6. Text(this.title)
    7. .fontSize(30)
    8. .fontWeight(FontWeight.Bold)
    9. .margin({left:10})
    10. }
    11. .width('100%')
    12. }
    13. }

    5、在第3点中新增的目录下新增ets文件ListComponent.ets

    1. @Component
    2. export struct ListComponent {
    3. @Prop name: string;
    4. @State isSwitch: boolean = false;
    5. build() {
    6. Row() {
    7. if(this.isSwitch) {
    8. Image($r("app.media.Selected"))
    9. .width(32)
    10. .height(32)
    11. } else {
    12. Image($r('app.media.NonSelect'))
    13. .width(32)
    14. .height(32)
    15. }
    16. Text(this.name)
    17. .fontSize(24)
    18. .fontColor(this.isSwitch? Color.Gray : Color.Black)
    19. .decoration({type: this.isSwitch? TextDecorationType.LineThrough : TextDecorationType.None})
    20. .margin({left:15,top:5,bottom:5})
    21. }
    22. .width('100%')
    23. .onClick( () => {
    24. this.isSwitch = !this.isSwitch
    25. })
    26. }
    27. }

    6、修改entry/src/main/pages/index.ets这个index入口页面为如下

    1. import { ListComponent } from '../view/ListComponent';
    2. import {TitleComponent} from '../view/TitleComponent';
    3. @Entry
    4. @Component
    5. struct Index {
    6. arr: string[] = ['JS','TS','ArkTs']
    7. build() {
    8. Column() {
    9. TitleComponent();
    10. Divider()
    11. ForEach(this.arr,(item) => {
    12. ListComponent({name: item.toString()})
    13. })
    14. }
    15. .width('100%')
    16. }
    17. }

    完在上面的操作后,选中index.ets,点击展开右边的预览窗品可以预览index页面的效果

    案例中相关知识点说明:

    条件渲染:if/else

    1. if(this.isSwitch) {
    2. Image($r("app.media.Selected"))
    3. .width(32)
    4. .height(32)
    5. } else {
    6. Image($r('app.media.NonSelect'))
    7. .width(32)
    8. .height(32)
    9. }

    循环渲染:ForEach

    1. ForEach(this.arr,(item) => {
    2. ListComponent({name: item.toString()})
    3. })

    @State装饰器:装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。

    @Prop装饰器:@State有相同的语义,但初始化方式不同。@Prop装饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量,但更改不会通知给父组件,即@Prop属于单向数据绑定。

  • 相关阅读:
    maven 重复依赖不同版本 选择规则
    科研诚信与学术规范MOOC-错题集
    Win11 Dev预览版25201.1000(rs_prerelease)发布:迎来全屏小组件
    力扣225.用队列实现栈
    pycharm2023.3专业版安装后打开无反应
    人工智能在软件测试领域的应用研究
    2.linux的组管理和权限管理
    Flink协调器Coordinator及自定义Operator
    [附源码]计算机毕业设计基于Springboot在线教育系统
    LeetCode刷题记录-简单模块(三)
  • 原文地址:https://blog.csdn.net/advent86/article/details/134375763