当前位置: 首页 > article >正文

鸿蒙NEXT开发-ArkTS(基于最新api12稳定版)

注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下

如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识

专栏地址: https://blog.csdn.net/qq_56760790/category_12794123.html

目录

1. ArkTS基本介绍

2. ArkTS语法

2.1 变量声明

2.2 常量声明

2.3 自动类型推断

2.4 联合类型

2.5 枚举类型

2.6 数组

2.7 函数

2.7.1 可选参数

2.7.2 Rest参数

2.7.3 返回类型

2.7.4 箭头函数(又名Lambda函数)

2.8 类

2.9 接口

2.10 对象

2.10.1 接口类型

2.10.2 类类型

2.11 泛型类型和函数

2.11.1 泛型类和接口

2.11.2 泛型约束

2.11.3 泛型函数

2.12 语句

2.12.1 if语句

2.12.2 Switch语句

2.12.3 条件表达式

2.12.4 For语句

2.12.5 For-of语句

2.12.6 While语句

2.12.7 Do-while语句

2.12.8 Break语句

2.12.9 Continue语句

2.13 模块

2.13.1 导出

2.13.2 导入

3. ArkTS组件结构

3.1 基于struct实现自定义组件

3.2 Component修饰符

3.3 Build函数

3.4 entry修饰符

3.5 组件复用

4. 视频学习链接


1. ArkTS基本介绍

ArkTS是HarmonyOS优选的主力应用开发语言。

ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,保持了TS的基本风格,同时通过规范定义强化开发期静态检查和分析,提升程序执行稳定性和性能。

从API version 10开始,ArkTS进一步通过规范强化静态检查和分析,对比标准TS的差异可以参考从TypeScript到ArkTS的适配规则:

  • 强制使用静态类型:静态类型是ArkTS最重要的特性之一。如果使用静态类型,那么程序中变量的类型就是确定的。同时,由于所有类型在程序实际运行前都是已知的,编译器可以验证代码的正确性,从而减少运行时的类型检查,有助于性能提升。
  • 禁止在运行时改变对象布局:为实现最大性能,ArkTS要求在程序执行期间不能更改对象布局。
  • 限制运算符语义:为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS限制了一些运算符的语义。比如,一元加法运算符只能作用于数字,不能用于其他类型的变量。
  • 不支持Structural typing:对Structural typing的支持需要在语言、编译器和运行时进行大量的考虑和仔细的实现,当前ArkTS不支持该特性。根据实际场景的需求和反馈,我们后续会重新考虑。

ArkTS它是纯新的一门语言,它不是前端也不是TypeScript,它是TS的超集

  • ArkTS的特性-扩展能力

  1. 基本语法
    • 定义声明式UI、自定义组件、动态扩展UI元素;
    • 提供ArkUI系统组件,提供组件事件、方法、属性;
    • 共同构成 UI 开发主体
  1. 状态管理
    • 组件状态、组件数据共享、应用数据共享、设备共享;
  1. 渲染控制
    • 条件渲染、循环渲染、数据懒加载;

ArkTS以声明方式组合和扩展组件来描述应用程序的UI,同时还提供了基本的属性、事件和子组件配置方法,帮助开发者实现应用交互逻辑。

  • 命令式UI- document.createElement("div")- <div>
  • 声明式UI

ArkTS提供了标准内置对象,例如Array、Map、TypedArray、Math等,供开发者直接使用。另外,ArkTS也提供了语言基础类库,为应用开发者提供常用的基础能力,主要包含能力如下图所示。

2. ArkTS语法

ArkTS通过声明引入变量、常量、函数和类型。

2.1 变量声明

以关键字let开头的声明引入变量,该变量在程序执行期间可以具有不同的值。

let hi: string = 'hello';
hi = 'hello, world';

2.2 常量声明

以关键字const开头的声明引入只读常量,该常量只能被赋值一次。

const hello: string = 'hello';

对常量重新赋值会造成编译时错误。

变量、常量的命名规则:

  • 只能包含数字、字母、下划线、$,不能以数字开头
  • 不能使用内置关键字或保留字(比如let const)
  • 严格区分大小写

2.3 自动类型推断

由于ArkTS是一种静态类型语言,所有数据的类型都必须在编译时确定。

但是,如果一个变量或常量的声明包含了初始值,那么开发者就不需要显式指定其类型。ArkTS规范中列举了所有允许自动推断类型的场景。

以下示例中,两条声明语句都是有效的,两个变量都是string类型:

let hi1: string = 'hello';
let hi2 = 'hello, world';

2.4 联合类型

联合类型是一种灵活的数据类型,它修饰的变量可以存储不同类型的数据;

语法:

let 变量:类型1|类型2|类型3 =值

let name:string|number;
name=1
name='东林'

2.5 枚举类型

枚举类型是一种特殊的数据类型,约定变量只能在一组数据范围内选择值

语法:

enum 枚举名{

常量1=值,

常量2=值

}

enum Color{
  Red='#ff0f29',
  Green='#30b30e'
}
// 使用枚举
let color:Color=Color.Red

2.6 数组

ArkTS基本数据类型(string、number、boolean等,语法跟ts差不多,大家可以在东林录制的视频前置课里面学习)

数组,是一个容器,可以存储多个数据;

语法:

let 数组名:类型[]=[数据1,数据2,....]

let names:string[]=['小头','东林']

注意:数组指定的类型和存储的数据类型必须要一致,否则会报错

数组中存储的每个数据,都有自己的编号,编号从0开始(索引)

联合类型:

let names:(string|number)[]=[1,2,'小头']

2.7 函数

函数:是可以被重复使用的代码块

定义函数:

function 函数名()

{

}

调用函数:

函数名()

函数的完整用法

function add(x: string, y: string): string {
  let z: string = `${x} ${y}`;
  return z;
}

2.7.1 可选参数

可选参数的格式可为name?: Type

function hello(name?: string) {
  if (name == undefined) {
    console.log('Hello!');
  } else {
    console.log(`Hello, ${name}!`);
  }
}

可选参数的另一种形式为设置的参数默认值。如果在函数调用中这个参数被省略了,则会使用此参数的默认值作为实参。

function multiply(n: number, coeff: number = 2): number {
  return n * coeff;
}
multiply(2);  // 返回2*2
multiply(2, 3); // 返回2*3

2.7.2 Rest参数

函数的最后一个参数可以是rest参数。使用rest参数时,允许函数或方法接受任意数量的实参。

function sum(...numbers: number[]): number {
  let res = 0;
  for (let n of numbers)
    res += n;
  return res;
}

sum() // 返回0
sum(1, 2, 3) // 返回6

2.7.3 返回类型

如果可以从函数体内推断出函数返回类型,则可在函数声明中省略标注返回类型。

// 显式指定返回类型
function foo(): string { return 'foo'; }

// 推断返回类型为string
function goo() { return 'goo'; }

不需要返回值的函数的返回类型可以显式指定为void或省略标注。这类函数不需要返回语句。

2.7.4 箭头函数(又名Lambda函数)

箭头函数是比普通函数更简洁的一种函数写法

函数可以定义为箭头函数,例如:

let sum = (x: number, y: number): number => {
  return x + y;
}

2.8 类

类声明引入一个新类型,并定义其字段、方法和构造函数。

在以下示例中,定义了Person类,该类具有字段name和surname、构造函数和方法fullName:

class Person {
  name: string = ''
  surname: string = ''
  constructor (n: string, sn: string) {
    this.name = n;
    this.surname = sn;
  }
  fullName(): string {
    return this.name + ' ' + this.surname;
  }
}

定义类后,可以使用关键字new创建实例:

let p = new Person('John', 'Smith');
console.log(p.fullName());

2.9 接口

接口声明引入新类型。接口是定义代码协定的常见方式。

任何一个类的实例只要实现了特定接口,就可以通过该接口实现多态。

接口通常包含属性和方法的声明

interface Style {
  color: string // 属性
}
interface AreaSize {
  calculateAreaSize(): number // 方法的声明
  someMethod(): void;     // 方法的声明
}

实现接口的类示例:

// 接口:
interface AreaSize {
  calculateAreaSize(): number // 方法的声明
  someMethod(): void;     // 方法的声明
}

// 实现:
class RectangleSize implements AreaSize {
  private width: number = 0
  private height: number = 0
  someMethod(): void {
    console.log('someMethod called');
  }
  calculateAreaSize(): number {
    this.someMethod(); // 调用另一个方法并返回结果
    return this.width * this.height;
  }
}

2.10 对象

语法:let 对象名称:对应结构类型=值

2.10.1 接口类型

interface People{
  name:string
  age:number
}

let pick:People={
  name:'pick',
  age:1
}

2.10.2 类类型

class People{
  name:string=''
  age:number=0
}

let pick:People={
  name:'pick',
  age:1
}

2.11 泛型类型和函数

泛型类型和函数允许创建的代码在各种类型上运行,而不仅支持单一类型。

2.11.1 泛型类和接口

类和接口可以定义为泛型,将参数添加到类型定义中,如以下示例中的类型参数Element:

class CustomStack<Element> {
  public push(e: Element):void {
    // ...
  }
}

要使用类型CustomStack,必须为每个类型参数指定类型实参:

let s = new CustomStack<string>();
s.push('hello');

2.11.2 泛型约束

泛型类型的类型参数可以被限制只能取某些特定的值。例如,MyHashMap<Key, Value>这个类中的Key类型参数必须具有hash方法。

interface Hashable {
  hash(): number
}
class MyHashMap<Key extends Hashable, Value> {
  public set(k: Key, v: Value) {
    let h = k.hash();
    // ...其他代码...
  }
}

在上面的例子中,Key类型扩展了Hashable,Hashable接口的所有方法都可以为key调用。

2.11.3 泛型函数

使用泛型函数可编写更通用的代码。比如返回数组最后一个元素的函数:

function last(x: number[]): number {
  return x[x.length - 1];
}
last([1, 2, 3]); // 3

如果需要为任何数组定义相同的函数,使用类型参数将该函数定义为泛型:

function last<T>(x: T[]): T {
  return x[x.length - 1];
}

2.12 语句

2.12.1 if语句

if语句用于需要根据逻辑条件执行不同语句的场景。当逻辑条件为真时,执行对应的一组语句,否则执行另一组语句(如果有的话)。

else部分也可能包含if语句。

if语句如下所示:

if (condition1) {
  // 语句1
} else if (condition2) {
  // 语句2
} else {
  // else语句
}

条件表达式可以是任何类型。但是对于boolean以外的类型,会进行隐式类型转换:

let s1 = 'Hello';
if (s1) {
  console.log(s1); // 打印“Hello”
}

let s2 = 'World';
if (s2.length != 0) {
  console.log(s2); // 打印“World”
}

2.12.2 Switch语句

使用switch语句来执行与switch表达式值匹配的代码块。

switch语句如下所示:

switch (expression) {
  case label1: // 如果label1匹配,则执行
    // ...
    // 语句1
    // ...
    break; // 可省略
  case label2:
  case label3: // 如果label2或label3匹配,则执行
    // ...
    // 语句23
    // ...
    break; // 可省略
  default:
    // 默认语句
}

2.12.3 条件表达式

条件表达式由第一个表达式的布尔值来决定返回其它两个表达式中的哪一个。

      condition ? expression1 : expression2

如果condition的为真值(转换后为true的值),则使用expression1作为该表达式的结果;否则,使用expression2。

2.12.4 For语句

for语句会被重复执行,直到循环退出语句值为false。

for ([init]; [condition]; [update]) {
  statements
}

2.12.5 For-of语句

使用for-of语句可遍历数组或字符串。示例如下:

for (forVar of expression) {
  statements
}

for (let ch of 'a string object') {
  /* process ch */
}

2.12.6 While语句

只要condition为真值(转换后为true的值),while语句就会执行statements语句。示例如下:

while (condition) {
  statements
}
let n = 0;
let x = 0;
while (n < 3) {
  n++;
  x += n;
}

2.12.7 Do-while语句

如果condition的值为真值(转换后为true的值),那么statements语句会重复执行。示例如下:

do {
  statements
} while (condition)
let i = 0;
do {
  i += 1;
} while (i < 10)

2.12.8 Break语句

使用break语句可以终止循环语句或switch。

let x = 0;
while (true) {
  x++;
  if (x > 5) {
    break;
  }
}

2.12.9 Continue语句

continue语句会停止当前循环迭代的执行,并将控制传递给下一个迭代。

let sum = 0;
for (let x = 0; x < 100; x++) {
  if (x % 2 == 0) {
    continue
  }
  sum += x;
}

2.13 模块

程序可划分为多组编译单元或模块。

每个模块都有其自己的作用域,即,在模块中创建的任何声明(变量、函数、类等)在该模块之外都不可见,除非它们被显式导出。

与此相对,从另一个模块导出的变量、函数、类、接口等必须首先导入到模块中。

2.13.1 导出

可以使用关键字export导出顶层的声明。

未导出的声明名称被视为私有名称,只能在声明该名称的模块中使用。

注意:通过export方式导出,在导入时要加{}。

export class Point {
  x: number = 0
  y: number = 0
  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number {
  return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
}

2.13.2 导入

导入声明用于导入从其他模块导出的实体,并在当前模块中提供其绑定。导入声明由两部分组成:

  • 导入路径,用于指定导入的模块;
  • 导入绑定,用于定义导入的模块中的可用实体集和使用形式(限定或不限定使用)。

导入绑定可以有几种形式。

假设模块具有路径“./utils”和导出实体“X”和“Y”。

导入绑定* as A表示绑定名称“A”,通过A.name可访问从导入路径指定的模块导出的所有实体:

import * as Utils from './utils'
Utils.X // 表示来自Utils的X
Utils.Y // 表示来自Utils的Y

导入绑定{ ident1, ..., identN }表示将导出的实体与指定名称绑定,该名称可以用作简单名称:

import { X, Y } from './utils'
X // 表示来自utils的X
Y // 表示来自utils的Y

如果标识符列表定义了ident as alias,则实体ident将绑定在名称alias下:

import { X as Z, Y } from './utils'
Z // 表示来自Utils的X
Y // 表示来自Utils的Y
X // 编译时错误:'X'不可见

3. ArkTS组件结构

ArkTS的基本组成

说明

自定义变量不能与基础通用属性/事件名重复。

ArkTS通过装饰器 @Component@Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件。
自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述,UI 描述的方法请参考 UI 描述规范。

3.1 基于struct实现自定义组件

要想实现一段UI的描述,必须使用struct关键字来声明- 注意不能有继承关系-组件名不能和系统组件名重名

语法: struct 组件名 {}

@Component
  struct Index {

  }

struct关键字声明的UI描述-必须被@Component修饰

3.2 Component修饰符

Component装饰器只能修饰struct关键字声明的结构,被修饰后的struct具备组件的描述(渲染)能力

3.3 Build函数

用于定义组件的UI描述,一个struct结构必须实现build函数

@Component
  struct MyComponent {
    build() {
    }
  }

3.4 entry修饰符

entry将自定义组件定义为UI页面的入口,也就是我们原来前端常说的一个页面,最多可以使用entry装饰一个自定义组件(在一个ets文件中)-如下面的代码就是不被允许的

@Entry
  @Component
  struct Index {

    build() {

    }
  }
@Entry
  @Component
  struct Index2 {
    build() {

    }
  }

entry修饰的组件,最终会被注册,具体文件位置-main/resources/base/profile/main_pages.json

  1. 自动注册-新建组件时,采用新建Page的方式
  2. 手动注册-新建一个ets文件,自己在main_pages.json中手动添加路径

3.5 组件复用

在很多情况下,由于业务的复杂度,我们经常会将一个大的业务拆成若干个组件,进行组装,这里我们非常灵活的复用组件,比如

  • 我们可以把上图抽象成三个组件- Header- Main- Footer
import Header from '../pages/Header';
import Main from '../pages/Main';
import Foot from '../pages/Foot';

@Entry
@Component
struct Demo {
  build() {
    Column() {
      Header().backgroundColor(Color.Pink)
      Main().backgroundColor(Color.Green)
      Foot().backgroundColor(Color.Red)
    }.height('100%')
    .width('100%')
  }
}

@Component
  export default struct Header {
    build() {
      Row() {
        Text('头部')
      }
      .width('100%')
        .height(60).justifyContent(FlexAlign.Center)
    }
  }

@Component
  export default struct Main{
    build() {
      Row(){
        Text('主体')
      }
      .width('100%').height('80%')
        .justifyContent(FlexAlign.Center)
    }
  }

@Component
  export  default  struct Foot{
    build() {
      Row(){
        Text('底部')
      }
      .width('100%').height('10%')
        .justifyContent(FlexAlign.Center)
    }
  }

总结:

  • 一个UI描述必须使用struct来声明,不能继承
  • struct必须被Component或者CustomDialog修饰
  • struct必须实现build方法,build方法可以没有元素,但是有的话有且只有一个可容纳子组件的容器组件(entry修饰的组件)
  • entry修饰符表示该组件是页面级组件,一个文件中只允许修饰一个struct组件
  • 采用分拆组件的形式可以有效解解耦我们的业务

4. 视频学习链接

全网首发鸿蒙NEXT星河版零基础入门到实战,2024年最新版,企业级开发!视频陆续更新中!_哔哩哔哩_bilibili


http://www.kler.cn/news/328102.html

相关文章:

  • 梯度检查点技术的使用
  • LINUX-线程
  • MySql基础34题写题记录(3-10)
  • 【tbNick专享】虚拟机域控、成员服务器、降级等管理
  • pip install kaggle-environments ISSUE:Failed to build vec-noise
  • MicoZone-Git
  • 深度剖析IT技术前沿:编织数字世界的未来篇章
  • 怎么通过AI大模型开发一个网站?
  • SQL第11课——使用子查询
  • 1.1.5 计算机网络的性能指标(下)
  • 作文网源码 范文论文网模板 带会员系统+支付接口+整站数据
  • docker_阿里云镜像仓库
  • 代码随想录算法训练营第56天 | 1、冗余连接,2、冗余连接II
  • 【数学分析笔记】第4章第2节 导数的意义和性质(1)
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-29
  • 谷歌发布Imagen 3,超过SD3、DALL・E-3,谷歌发布新RL方法,性能提升巨大,o1模型已证明
  • Python 封装 socket 为 [TCP/UDP/MULTICAST] 客户端
  • powerbi计算销售额同比增长率
  • MySql Explain优化命令使用
  • Vue实战教程:如何用JS封装一个可复用的Loading组件
  • 基于php的律所管理系统
  • leetcode 513 找到左下角的值
  • SQLite3模块使用详解
  • 使用WebClient 快速发起请求(不使用WebClientUtils工具类)
  • 测试面试题:pytest断言时,数据是符点类型,如何断言?
  • 【Python|接口自动化测试】使用requests发送http请求时添加headers
  • 【LeetCode】每日一题 2024_9_27 每种字符至少取 K 个(双指针)
  • Android 安装应用-提交阶段之后剩下的操作
  • uniapp生物识别示例(人脸识别、指纹识别)
  • 【docker】docker常见命令