0.先建立正确认识:ArkTS、TypeScript 与 ArkUI 分别是什么

初学 HarmonyOS 时,最容易混淆的有三个名词:
名称	你可以把它理解为	主要解决的问题
JavaScript	基础编程语言	“让程序做事”
TypeScript	JavaScript 加上类型检查	“让代码更不容易写错”
ArkTS	HarmonyOS 面向应用开发的 TypeScript 方言	“用更规范、更安全的方式写 HarmonyOS 代码”
ArkUI	HarmonyOS 的声明式 UI 框架	“把数据画成页面,并响应用户点击”

一句话记忆:
• ArkTS 是写逻辑、类型和数据的语言。
• ArkUI 是用 ArkTS 描述界面的方式。
• 你在 .ets 文件里通常会同时写“数据处理代码”和“页面代码”。
例如:

let userName: string = '小明'; // ArkTS:定义数据

Text(`你好,${userName}`) // ArkUI:把数据画到屏幕上

1. 第一个页面长什么样

打开新项目中的 Index.ets,常会看到类似下面的结构:

@Entry
@Component
struct Index {
  @State message: string = '你好,ArkTS!'

  build() {
    Column() {
      Text(this.message)
        .fontSize(28)

      Button('点我')
        .margin({ top: 16 })
        .onClick(() => {
          this.message = '你刚刚点击了按钮'
        })
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

运行后,页面上会显示一句文字和一个按钮。点击按钮,文字会改变。
先不要急着记住全部语法。你只要先理解这四件事:

  1. struct Index:定义一个叫 Index 的页面组件。
  2. @State message:定义会影响页面显示的数据。
  3. build():描述页面“应该长什么样”。
  4. onClick:描述用户点击按钮后“应该做什么”。

1.1 @Entry:应用入口页面

@Entry
@Component
struct Index {
  build() {
    Text('我是应用启动后最先显示的页面')
  }
}

@Entry 表示:这个组件是一个页面入口。一个页面文件通常只需要一个 @Entry 组件。

1.2 @Component:这是一个 UI 组件

@Component
struct WelcomeCard {
  build() {
    Text('欢迎学习 ArkTS')
  }
}

有了 @Component,ArkUI 才知道这个 struct 不是普通数据结构,而是一个可绘制到屏幕上的组件。

1.3 build():页面的“说明书”

在 build() 中,你不是手工创建像素,而是在声明:
页面里有哪些组件,它们按什么顺序排列,使用什么数据,拥有怎样的样式。

build() {
  Column() {
    Text('第一行')
    Text('第二行')
    Button('第三个控件')
  }
}

这段代码表示纵向排列:

第一行
第二行
[第三个控件]

2. 注释:给未来的自己写说明

注释不会执行,只是解释代码。

// 单行注释:这一行不会执行

/*
  多行注释:
  可以写很多行说明。
*/

推荐养成两个习惯:
• 对“为什么这样写”添加注释。
• 不要给显而易见的语句添加无意义注释。
不太有帮助:

let age: number = 18; // 定义年龄

更有帮助:

// 订单金额以“分”为单位保存,避免浮点数计算误差
let amountInFen: number = 1999;

3. 变量:让程序记住数据

变量可以理解为“有名字的盒子”。你把数据放进盒子,后续通过名字取出来。
ArkTS 中最常用的变量声明方式是 let 和 const。

let score: number = 60;
score = 95;

const appName: string = '学习助手';
// appName = '新名称'; // 错误:const 声明的变量不能重新赋值

3.1 let 和 const 怎么选

在这里插入图片描述

let page: number = 1;
page = 2;

const maxPageSize: number = 20;

初学时可以采用简单规则:
默认先写 const;只有确实需要改变变量值时,才使用 let。

3.2 不推荐随意使用 var

你可能会在旧 JavaScript 教程中看到 var:
var oldStyle: string = ‘旧写法’;
现代 ArkTS 开发中优先使用 let 和 const。它们的作用范围更清楚,更不容易产生难以排查的错误。

4. 基本数据类型:给数据贴上“标签”

类型告诉编译器:这个变量里准备装什么数据。

let name: string = '小华';
let age: number = 18;
let isStudent: boolean = true;

4.1 string:文本

文本必须用单引号、双引号或反引号包起来。

let city: string = '深圳';
let school: string = "鸿蒙学院";
let greeting: string = `欢迎来到 ${city}`;

推荐使用模板字符串(反引号)拼接文本:

let userName: string = '小华';
let age: number = 18;

let text: string = `我是${userName},今年${age}岁。`;

不推荐初学时大量使用 + 拼接:
let text: string = ‘我是’ + userName + ‘,今年’ + age + ‘岁。’;
模板字符串可读性更好。
常用文本操作:

let title: string = '  ArkTS 入门  ';

let length: number = title.length;          // 文本长度
let upper: string = title.toUpperCase();    // 转大写
let lower: string = title.toLowerCase();    // 转小写
let clean: string = title.trim();           // 去掉首尾空格
let hasArk: boolean = title.includes('Ark'); // 是否包含某文本

4.2 number:数字

number 可表示整数和小数。

let count: number = 10;
let price: number = 19.9;
let total: number = count * price;

常见运算符:
在这里插入图片描述

let apples: number = 10;
apples = apples + 1;
apples += 1; // 等价于 apples = apples + 1

4.3 boolean:真或假

布尔值只有两个:

let isLogin: boolean = true;
let isVip: boolean = false;

注意:true 和 false 不要加引号。加了引号后它们会变成文本。

let correct: boolean = true;
let wrong: string = 'true';

4.4 undefined 与 null:没有值,要谨慎处理

初学阶段最重要的原则是:
不确定数据是否存在时,先检查,再使用。

let nickName: string | undefined = undefined;

if (nickName !== undefined) {
  console.info(nickName.toUpperCase());
} else {
  console.info('用户尚未设置昵称');
}

string | undefined 的意思是:这个变量要么是文本,要么没有值。

5. 类型推断:有时可以不手写类型

如果右侧的值非常明确,ArkTS 通常可以自动推断类型:

let name = '小明';    // 推断为 string
let age = 20;         // 推断为 number
let isReady = true;   // 推断为 boolean

不过在学习阶段、函数参数、对象结构、接口边界处,建议明确写出类型:

let courseName: string = 'ArkTS';
let lessonCount: number = 12;

这样你自己和编译器都更容易发现问题。

6. 运算与比较:程序如何“判断”

6.1 比较运算符

let score: number = 85;

console.info(score > 60);   // true
console.info(score >= 85);  // true
console.info(score < 100);  // true
console.info(score === 85); // true
console.info(score !== 85); // false

初学时请优先使用严格相等 === 和严格不等 !==。

let value: number = 1;

// 推荐
if (value === 1) {
  console.info('值为 1');
}

6.2 逻辑运算符

let age: number = 20;
let hasTicket: boolean = true;

let canEnter: boolean = age >= 18 && hasTicket;
let needsHelp: boolean = age < 18 || !hasTicket;

在这里插入图片描述

7. 条件判断:让程序做不同选择

7.1 if / else if / else

function getLevel(score: number): string {
  if (score >= 90) {
    return '优秀';
  } else if (score >= 60) {
    return '及格';
  } else {
    return '需要继续努力';
  }
}

调用:

let result: string = getLevel(85);
console.info(result); // 及格

读代码时可以按自然语言理解:

如果 分数大于等于 90:优秀
否则如果 分数大于等于 60:及格
否则:需要继续努力

7.2 三元表达式:简单二选一

当判断只有两个结果时可使用:

let isLogin: boolean = true;
let displayText: string = isLogin ? '欢迎回来' : '请先登录';

格式是:

条件 ? 条件成立时的值 : 条件不成立时的值

不要把过于复杂的业务逻辑塞进三元表达式;复杂时请改用 if。

7.3 switch:多个固定选项

function getWeekText(day: number): string {
  switch (day) {
    case 1:
      return '星期一';
    case 2:
      return '星期二';
    case 3:
      return '星期三';
    default:
      return '其他日期';
  }
}

当你是在比较“一个值对应多个固定情况”时,switch 很合适。

8. 循环:重复做一件事

8.1 for 循环

for (let index: number = 1; index <= 5; index++) {
  console.info(`第 ${index} 次练习`);
}

它由三部分组成:

for (初始化; 继续条件; 每轮结束后的变化) {
  重复执行的代码
}

8.2 遍历数组:for…of

let fruits: string[] = ['苹果', '香蕉', '橙子'];

for (const fruit of fruits) {
  console.info(fruit);
}

对于初学者,读取数组中的每一项时,优先考虑 for…of。它比手动写下标更直观。

8.3 while 循环

let current: number = 1;

while (current <= 3) {
  console.info(`当前值:${current}`);
  current++;
}

使用 while 时一定要确保循环条件最终会变成 false,否则可能出现死循环。
错误示例:

let count: number = 1;

// 不要运行这样的代码:count 永远没有变化
// while (count <= 3) {
//   console.info(count);
// }

9. 数组:按顺序保存一组数据

数组用于保存多个同类数据。

let scores: number[] = [80, 90, 100];
let names: string[] = ['小红', '小蓝', '小绿'];

9.1 读取数组元素

数组下标从 0 开始:

let cities: string[] = ['北京', '上海', '广州'];

console.info(cities[0]); // 北京
console.info(cities[1]); // 上海

9.2 常用数组操作

let tasks: string[] = ['学习变量', '学习函数'];

tasks.push('学习组件'); // 末尾添加
console.info(tasks.length);

let firstTask: string | undefined = tasks.shift(); // 删除并取得第一个元素
console.info(firstTask);

在 UI 状态中,推荐返回新数组,而不是就地修改复杂对象。这样页面更新更稳定、代码也更容易理解:

let oldList: number[] = [1, 2, 3];
let newList: number[] = oldList.map((item: number) => item * 2);

// oldList 是 [1, 2, 3]
// newList 是 [2, 4, 6]

9.3 常见数组方法

let scores: number[] = [60, 75, 90, 100];

let passed: number[] = scores.filter((score: number) => score >= 60);
let doubled: number[] = scores.map((score: number) => score * 2);
let hasPerfect: boolean = scores.some((score: number) => score === 100);
let allPassed: boolean = scores.every((score: number) => score >= 60);

它们的语义是:
在这里插入图片描述

10. 对象:描述一件有多个属性的事物

如果一个学生不仅有姓名,还有年龄和是否已报名,就适合用对象:

let student: {
  name: string;
  age: number;
  enrolled: boolean;
} = {
  name: '小明',
  age: 18,
  enrolled: true
};

console.info(student.name);
console.info(student.age);

但对象字段较多时,建议使用 interface。

11. interface:给对象制定统一结构

接口是一份“数据结构约定”。它不直接创建对象,而是规定对象必须有什么字段、每个字段是什么类型。

interface Student {
  id: number;
  name: string;
  age: number;
  enrolled: boolean;
}

按接口创建对象:

let student: Student = {
  id: 1,
  name: '小明',
  age: 18,
  enrolled: true
};

如果漏掉字段,编译器会提醒你:

// 错误示意:缺少 enrolled
// let invalidStudent: Student = {
//   id: 2,
//   name: '小红',
//   age: 19
// };

11.1 可选属性 ?

有些属性可以没有:

interface UserProfile {
  id: number;
  name: string;
  avatarUrl?: string;
}

let user: UserProfile = {
  id: 1,
  name: '小华'
};

读取可选属性时要兜底:

let avatarText: string = user.avatarUrl ?? '未设置头像';
console.info(avatarText);

?? 的意思是:如果左边是 null 或 undefined,就使用右边的默认值。

12. 函数:把可重复的逻辑装起来

函数相当于一个可重复调用的小工具。

function sayHello(): void {
  console.info('你好,ArkTS!');
}

调用函数:

sayHello();

12.1 带参数的函数

function greet(name: string): string {
  return `你好,${name}!`;
}

let message: string = greet('小明');
console.info(message);

这里:
• name: string 是输入参数。
• : string 是函数返回值的类型。
• return 表示把结果交还给调用者。

12.2 没有返回值:void

function printWelcome(): void {
  console.info('欢迎开始学习');
}

void 表示该函数只做事情,不返回可供保存的结果。

12.3 多个参数

function add(left: number, right: number): number {
  return left + right;
}

let sum: number = add(3, 5);

12.4 默认参数

function createTitle(text: string, prefix: string = '课程:'): string {
  return `${prefix}${text}`;
}

console.info(createTitle('ArkTS 入门'));
console.info(createTitle('ArkUI 布局', '章节:'));

12.5 箭头函数

箭头函数常用于按钮点击、数组处理等场景:

let multiply = (left: number, right: number): number => {
  return left * right;
};

console.info(multiply(2, 3));

当只有一行返回值时可以简写:

let square = (value: number): number => value * value;
ArkUI 中你会经常见到:
Button('点击')
  .onClick(() => {
    console.info('按钮被点击');
  })

这个 () => {} 就是“点击发生时再执行的函数”。

13. 类:把数据和行为放在一起

类适合描述“有状态、有行为”的对象。

class Counter {
  private value: number = 0;

  increase(): void {
    this.value++;
  }

  getValue(): number {
    return this.value;
  }
}

let counter: Counter = new Counter();
counter.increase();
console.info(counter.getValue()); // 1

理解关键字:
在这里插入图片描述
初学阶段可以优先掌握 interface 和函数;当业务对象确实需要封装方法与内部状态时,再使用类。

14. 枚举:给有限选项取名字

例如任务状态只有三种,与其到处写数字,不如使用枚举:

enum TaskStatus {
  Todo,
  Doing,
  Done
}

let status: TaskStatus = TaskStatus.Doing;

if (status === TaskStatus.Doing) {
  console.info('任务正在进行');
}

枚举让代码更容易读:

// 不够直观
let state: number = 1;

// 更直观
let state: TaskStatus = TaskStatus.Doing;

15. 联合类型、类型别名与类型守卫

15.1 联合类型

一个值有时可以是多种类型之一:

let orderId: number | string = 1001;
orderId = 'A-1002';

但使用前要先判断真实类型:

function formatOrderId(id: number | string): string {
  if (typeof id === 'number') {
    return `数字订单:${id}`;
  }
  return `文本订单:${id.toUpperCase()}`;
}

这里的 typeof 判断叫做一种类型守卫:它帮助编译器确认某段代码中的实际类型。

15.2 类型别名 type

如果一段类型定义比较长,可以取一个名字:

type CourseLevel = '初级' | '中级' | '高级';

let level: CourseLevel = '初级';

这能限制值只能是三个指定文本之一。

16. 异常处理:预料失败,而不是害怕失败

程序可能遇到网络失败、数据格式不对、权限不足等问题。对可能抛出异常的逻辑,可以使用 try / catch:

function parseScore(text: string): number {
  let result: number = Number(text);

  if (Number.isNaN(result)) {
    throw new Error('分数不是有效数字');
  }

  return result;
}

try {
  let score: number = parseScore('90');
  console.info(`分数为:${score}`);
} catch (error) {
  console.error(`处理失败:${String(error)}`);
}

初学时先记住这个模式:

try {
  // 可能失败的代码
} catch (error) {
  // 失败后的处理
}

不要为了“看起来安全”而吞掉错误。至少应记录错误或给用户一个明确提示。

17. 异步编程:等待耗时操作完成

网络请求、文件读写、数据库操作通常不会瞬间完成。异步代码允许程序等待结果,而不把页面完全卡住。

17.1 Promise

Promise 可以理解为“未来会拿到一个 T 类型的结果”。

function getCourseName(): Promise<string> {
  return Promise.resolve('ArkTS 零基础课程');
}

17.2 async / await

推荐的异步写法:

async function loadCourse(): Promise<void> {
  let courseName: string = await getCourseName();
  console.info(courseName);
}

含义是:

  1. getCourseName() 开始获取数据。
  2. await 等待它完成。
  3. 得到文本后,赋值给 courseName。
  4. 继续执行后面的代码。
    在 ArkUI 中,常见写法如下:
async function loadMessage(): Promise<string> {
  return Promise.resolve('异步数据加载完成');
}

@Entry
@Component
struct AsyncExample {
  @State message: string = '尚未加载'

  build() {
    Column() {
      Text(this.message)

      Button('加载数据')
        .onClick(async () => {
          this.message = '加载中...';
          this.message = await loadMessage();
        })
    }
  }
}

提示:真实项目中会把网络请求、错误处理、加载状态和空数据状态都考虑进去;学习阶段先掌握 async、await 和 Promise 的关系即可。

18. ArkUI 基础布局:页面如何摆放

最常用的容器有:
在这里插入图片描述

18.1 Column

Column({ space: 12 }) {
  Text('标题')
  Text('内容')
  Button('确认')
}
.width('100%')
.padding(16)

18.2 Row

Row({ space: 8 }) {
  Text('用户名:')
  Text('小明')
}
.width('100%')

18.3 Stack

后写的组件会覆盖在先写的组件上方:

Stack({ alignContent: Alignment.BottomStart }) {
  Image($r('app.media.app_icon'))
    .width(120)
    .height(120)

  Text('推荐')
    .fontColor(Color.White)
    .backgroundColor(Color.Red)
    .padding(6)
}

如果你的项目中没有对应图片资源,可先不运行这段图片示例;Column、Row 和 Text 不依赖额外资源,可以直接运行。

19. 样式链式调用:组件后面的点号在做什么

观察下面代码:

Text('ArkTS')
  .fontSize(24)
  .fontWeight(FontWeight.Bold)
  .fontColor(Color.Blue)
  .margin({ bottom: 12 })

它表示“创建一个文本”,然后连续设置它的样式。
常用样式:

Text('示例文本')
  .fontSize(18)
  .fontColor('#333333')
  .fontWeight(FontWeight.Medium)
  .textAlign(TextAlign.Center)
  .width('100%')
  .padding(12)
  .backgroundColor('#F1F3F5')
  .borderRadius(8)

常用尺寸单位:
• 24:通常表示 vp(虚拟像素),适合布局尺寸。
• ‘100%’:相对父组件宽度或高度。
• 12:可用于 padding、margin、fontSize 等常用属性。
初学时不必把所有属性死记硬背。先会查组件的属性提示,并逐步积累。

20. @State:页面为什么会自动刷新

@State 是 ArkUI 最重要的入门概念之一。
@Entry
@Component
struct StateExample {
  @State count: number = 0

  build() {
    Column({ space: 12 }) {
      Text(`当前计数:${this.count}`)
        .fontSize(24)

      Button('+1')
        .onClick(() => {
          this.count++;
        })
    }
  }
}

点击按钮后,count 变化,页面中的 Text 会自动显示新值。
可以这样理解:

@State 数据变化
        ↓
ArkUI 发现这个数据被页面使用
        ↓
相关 UI 自动重新计算并刷新

20.1 普通变量与 @State 的差别

@Component
struct WrongExample {
count: number = 0 // 普通字段,不适合作为需要驱动 UI 刷新的页面状态


build() {
  Column() {
    Text(`${this.count}`)
    Button('+1').onClick(() => {
      this.count++;
    })
  }
}
}

对于“用户点击后要立即反映到界面上”的数据,应使用 @State:

@State count: number = 0

20.2 状态设计的小原则

适合 @State 的数据:
• 输入框中正在输入的文字。
• 当前选中的标签。
• 列表中的任务数据。
• 加载中、加载成功、加载失败的页面状态。
• 当前计数、当前页码。
不适合把所有数据都无脑放进 @State。例如不会影响当前页面展示的常量、工具对象、一次性临时计算结果,通常不需要页面状态装饰。

21. 组件通信:父组件把数据交给子组件

21.1 @Prop:父传子,子组件只读使用

@Component
struct UserGreeting {
  @Prop name: string = '访客'

  build() {
    Text(`你好,${this.name}`)
  }
}

@Entry
@Component
struct ParentPage {
  build() {
    Column() {
      UserGreeting({ name: '小明' })
      UserGreeting({ name: '小红' })
    }
  }
}

父组件使用子组件时像传参数一样传入:

UserGreeting({ name: '小明' })

21.2 @Link:父子共享可修改状态

当子组件既要展示数据,又要修改父组件的状态,可以使用

@Link:
@Component
struct CounterButton {
  @Link count: number

  build() {
    Button(`子组件加 1:${this.count}`)
      .onClick(() => {
        this.count++;
      })
  }
}

@Entry
@Component
struct ParentCounterPage {
  @State count: number = 0

  build() {
    Column({ space: 12 }) {
      Text(`父组件计数:${this.count}`)
        .fontSize(24)

      CounterButton({ count: $count })
    }
    .padding(24)
  }
}

注意传入时是 $count,不是 count:

CounterButton({ count: $count })

初学记忆:
在这里插入图片描述

22. 页面渲染语法:条件显示和循环显示

22.1 if:有条件地显示组件

@Entry
@Component
struct LoginPage {
  @State isLogin: boolean = false

  build() {
    Column({ space: 12 }) {
      if (this.isLogin) {
        Text('欢迎回来!')
          .fontSize(24)
      } else {
        Text('请先登录')
          .fontSize(24)
      }

      Button(this.isLogin ? '退出登录' : '登录')
        .onClick(() => {
          this.isLogin = !this.isLogin;
        })
    }
    .padding(24)
  }
}

这里 if 不是普通函数中的条件,而是在 build() 中决定“显示哪一组 UI”。

22.2 ForEach:把数组画成列表

@Entry
@Component
struct FruitPage {
  @State fruits: string[] = ['苹果', '香蕉', '橙子']

  build() {
    Column({ space: 8 }) {
      ForEach(this.fruits, (fruit: string) => {
        Text(fruit)
          .fontSize(20)
          .width('100%')
          .padding(12)
          .backgroundColor('#F1F3F5')
          .borderRadius(8)
      }, (fruit: string) => fruit)
    }
    .padding(16)
  }
}

ForEach 的三个部分:

ForEach(
  数据数组,
  每一项如何绘制,
  每一项的唯一标识
)

最后的唯一标识很重要。真实列表中建议使用稳定的 id,不要只依赖容易重复或变化的文本。

23. 输入与事件:让用户和页面互动

23.1 TextInput

@Entry
@Component
struct InputPage {
  @State inputText: string = ''

  build() {
    Column({ space: 12 }) {
      TextInput({ placeholder: '请输入你的名字', text: this.inputText })
        .onChange((value: string) => {
          this.inputText = value;
        })

      Text(this.inputText.length > 0 ? `你好,${this.inputText}` : '还没有输入内容')
    }
    .padding(24)
  }
}

核心关系:

输入框内容变化
      ↓
onChange 接收到 value
      ↓
更新 @State inputText
      ↓
Text 使用新值重新显示

23.2 常用事件

Button('点击')
  .onClick(() => {
    console.info('点击事件');
  });

TextInput({ placeholder: '输入内容' })
  .onChange((value: string) => {
    console.info(`输入内容:${value}`);
  });

事件函数不要写成立即执行:

// 错误示意:不要这样写
// .onClick(this.doSomething())

应该传入一个函数:

.onClick(() => {
  this.doSomething();
})

24. 资源引用:$r() 是什么

HarmonyOS 项目中的资源通常放在 resources 目录。引用字符串、颜色、图片等资源时,经常会看到 $r():

Text($r('app.string.app_name'))

Image($r('app.media.app_icon'))

可以粗略理解为:
“到应用资源文件中,按资源名取出对应内容。”
初学阶段,直接使用文本和颜色即可:

Text('欢迎学习 ArkTS')
  .fontColor('#0A59F7')

当项目需要多语言、统一主题和可维护图片资源时,再逐步学习资源文件的组织方式。

25. ArkTS 初学者最常遇到的错误

25.1 把文本忘记加引号

// 错误
// let name: string = 小明;

// 正确
let name: string = '小明';

25.2 把 = 与 === 混淆

let score: number = 90;

// 正确:比较
if (score === 90) {
  console.info('满分');
}

• =:赋值。
• ===:比较是否相等。

25.3 忘记使用 this

在组件内部访问字段时通常要写 this.:

@State count: number = 0

// 正确
this.count++;

25.4 把会改变页面的变量写成普通字段

// 要让 UI 自动刷新,使用 @State
@State title: string = '初始标题';

25.5 ForEach 中没有稳定唯一标识

列表有增加、删除、排序等操作时,尽量使用业务唯一 id:

interface Todo {
  id: number;
  title: string;
}

ForEach(this.todos, (item: Todo) => {
  Text(item.title)
}, (item: Todo) => item.id.toString())

25.6 把复杂业务全塞进 build()

build() 应主要负责描述 UI。复杂计算、数据转换、网络调用可以提取成函数:

private getWelcomeText(): string {
  return this.userName.length > 0 ? `你好,${this.userName}` : '你好,访客';
}

build() {
  Text(this.getWelcomeText())
}

26. 完整可运行示例:ArkTS 语法实验室

把下面完整代码复制到 entry/src/main/ets/pages/Index.ets,替换原有内容后运行。点击按钮即可在页面上看到变量、数组、对象、函数、类、枚举和异步语法的执行结果。

enum LearningStatus {
  NotStarted,
  Learning,
  Finished
}

interface Learner {
  name: string;
  age: number;
  courses: string[];
}

class SimpleCounter {
  private value: number = 0;

  increase(): void {
    this.value++;
  }

  getValue(): number {
    return this.value;
  }
}

function getLevel(score: number): string {
  if (score >= 90) {
    return '优秀';
  } else if (score >= 60) {
    return '及格';
  }
  return '继续努力';
}

function getAsyncMessage(): Promise<string> {
  return Promise.resolve('异步任务已完成:你已经掌握了 async / await 的基本写法。');
}

@Entry
@Component
struct Index {
  @State resultText: string = '点击“运行示例”,在这里查看输出。'

  build() {
    Column({ space: 16 }) {
      Text('ArkTS 语法实验室')
        .fontSize(26)
        .fontWeight(FontWeight.Bold)

      Text(this.resultText)
        .fontSize(16)
        .lineHeight(24)
        .width('100%')
        .padding(16)
        .backgroundColor('#F1F3F5')
        .borderRadius(12)

      Button('运行示例')
        .width('100%')
        .onClick(async () => {
          await this.runDemo();
        })
    }
    .width('100%')
    .height('100%')
    .padding(24)
    .justifyContent(FlexAlign.Center)
  }

  private async runDemo(): Promise<void> {
    const appName: string = 'ArkTS 入门';
    let score: number = 88;
    const isLearning: boolean = true;

    const learner: Learner = {
      name: '小明',
      age: 18,
      courses: ['变量', '函数', '组件']
    };

    const counter: SimpleCounter = new SimpleCounter();
    counter.increase();
    counter.increase();

    const status: LearningStatus = LearningStatus.Learning;
    const courseText: string = learner.courses.join('、');
    const level: string = getLevel(score);
    const asyncMessage: string = await getAsyncMessage();

    this.resultText =
      `课程:${appName}\n` +
      `学习者:${learner.name},${learner.age} 岁\n` +
      `正在学习:${isLearning ? '是' : '否'}\n` +
      `课程列表:${courseText}\n` +
      `分数:${score},评价:${level}\n` +
      `计数器值:${counter.getValue()}\n` +
      `学习状态枚举值:${status}\n` +
      `${asyncMessage}`;
  }
}

你可以尝试自己修改:

  1. 把 score 改成 95,观察评价变化。
  2. 在 courses 中增加 ‘异步编程’。
  3. 多调用一次 counter.increase()。
  4. 把 learner.name 改成你自己的名字。

27 一份速查表

在这里插入图片描述
在这里插入图片描述

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐