鸿蒙HarmonyOS实战-ArkTS语言(基本语法)
??一、ArkTS語言基本語法
??1.簡介
HarmonyOS的ArkTS語言是一種基于TypeScript開發的語言,它專為HarmonyOS系統開發而設計。ArkTS語言結合了JavaScript的靈活性和TypeScript的嚴謹性,使得開發者能夠快速、高效地開發出高質量的HarmonyOS應用程序。
ArkTS語言具有以下特點:
靜態類型檢查:開發者在編寫代碼時可以使用類型注解來進行類型檢查,從而減少因類型錯誤而導致的bug。
異步/同步編程:ArkTS語言支持基于Promise和async/await的異步/同步編程方式,能夠更好地處理異步操作。
內置模塊:ArkTS語言內置了許多常用的模塊,如文件系統、網絡請求、圖形渲染等,使得開發者不必自己編寫這些模塊。
兼容性:ArkTS語言使用TypeScript語法,可以與JavaScript代碼無縫集成,并且可以編譯成JavaScript代碼來在其他平臺上運行。
ArkTS語言基礎類庫是HarmonyOS系統上為應用開發者提供的常用基礎能力,主要包含能力如下圖所示:
ArkTS是HarmonyOS優選的主力應用開發語言。ArkTS圍繞應用開發在TypeScript(簡稱TS)生態基礎上做了進一步擴展,繼承了TS的所有特性,是TS的超集。
ArkTS和HTML的差別:
??2.TypeScript的基礎語法
TypeScript是一種由微軟開發的JavaScript超集語言,它支持JavaScript的所有語法,但添加了一些新的特性和語法,使開發更加可靠和高效。TypeScript最大的特點是引入了靜態類型,開發者可以在編譯時發現類型錯誤,提高代碼的可維護性和可讀性。
TypeScript代碼可以在編譯時被轉換成JavaScript代碼,在瀏覽器和Node.js環境下都可以運行。雖然TypeScript相對于JavaScript來說更加復雜,但是它可以幫助開發者更好地組織和管理復雜的項目,特別是在團隊協作中提高代碼的質量和可維護性。
TypeScript基礎知識包括基本類型、變量聲明、函數、類、接口、泛型等。另外,TypeScript還支持模塊化開發,可以使用ES模塊規范或者CommonJS規范導入和導出模塊。在實際項目開發中,TypeScript還可以結合工具鏈如Webpack、Babel進行編譯、打包等操作。
除了上面提到的變量聲明、函數定義、類定義、接口定義和枚舉類型外,TypeScript還有一些基礎語法需要掌握:
??2.1 類型注解
TypeScript的靜態類型檢查是通過類型注解實現的。在聲明變量或函數時,可以使用冒號加上類型注解,指定變量或函數的類型。例如:
let name: string = "TypeScript";
function add(a: number, b: number): number {
return a + b;
}
??2.2 接口
TypeScript的接口是用來描述對象的形狀的。可以定義對象需要包含哪些屬性和方法,以及它們的類型。例如:
interface Person {
name: string;
age: number;
sayHello(): void;
}
let tom: Person = {
name: "Tom",
age: 18,
sayHello: function() {
console.log(`Hello, my name is ${this.name}!`);
}
};
??2.3 泛型
TypeScript的泛型可以幫助我們編寫更加靈活、可重用的代碼。它允許在編寫函數、類或接口時使用參數化類型,從而提高代碼的通用性和可讀性。例如:
function identity<T>(arg: T): T {
<details>
<summary>點擊查看代碼</summary>
function identity
return arg;
}
let output = identity
console.log(output); // 輸出 TypeScript
</details>
return arg;
}
let output = identity<string>("TypeScript");
console.log(output); // 輸出 TypeScript
??2.4 類的繼承
TypeScript的類可以繼承其他類,從而實現代碼的重用和擴展。通過關鍵字extends可以讓一個類繼承另一個類,并繼承其屬性和方法。例如:
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
move(distance: number = 0) {
console.log(`${this.name} moved ${distance}m.`);
}
}
class Dog extends Animal {
bark() {
console.log("Woof! Woof!");
}
}
let dog = new Dog("Bobby");
dog.move(10); // 輸出 "Bobby moved 10m."
dog.bark(); // 輸出 "Woof! Woof!"
??2.5 類的訪問修飾符
TypeScript的類可以通過訪問修飾符來控制類的屬性和方法的訪問權限。有三個訪問修飾符可以使用:public、private和protected。默認情況下,都是public。
public:公共的,任何外部或內部都可以訪問。
private:私有的,只有類的內部可以訪問,外部無法訪問。
protected:受保護的,只有類的內部和其子類可以訪問,外部無法訪問。
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
protected sayHello() {
console.log(`Hello, I'm ${this.name}.`);
}
}
class Student extends Person {
constructor(name: string) {
super(name);
}
public sayHelloToTeacher(teacher: Person) {
console.log(`Hello, ${teacher.name}, I'm ${this.name}.`);
}
}
let tom = new Student("Tom");
let bob = new Person("Bob");
tom.sayHelloToTeacher(bob); // 輸出 "Hello, Bob, I'm Tom."
bob.sayHello(); // 報錯:屬性 'sayHello' 受保護,只能在類 'Person' 及其子類中訪問。
以上只是舉例一些TS的基礎語法,TS內容遠不止這些不懂的可以去學學TS。
??3.ArkTS的基本組成
裝飾器:用于裝飾類、結構、方法以及變量,并賦予其特殊的含義。如上述示例中@Entry、@Component和@State都是裝飾器,@Component表示自定義組件,@Entry表示該自定義組件為入口組件,@State表示組件中的狀態變量,狀態變量變化會觸發UI刷新。
UI描述:以聲明式的方式來描述UI的結構,例如build()方法中的代碼塊。
自定義組件:可復用的UI單元,可組合其他組件,如上述被@Component裝飾的struct Hello。
系統組件:ArkUI框架中默認內置的基礎和容器組件,可直接被開發者調用,比如示例中的Column、Text、Divider、Button。
屬性方法:組件可以通過鏈式調用配置多項屬性,如fontSize()、width()、height()、backgroundColor()等。
事件方法:組件可以通過鏈式調用設置多個事件的響應邏輯,如跟隨在Button后面的onClick()。
系統組件、屬性方法、事件方法具體使用可參考基于ArkTS的聲明式開發范式。
除此之外,ArkTS擴展了多種語法范式來使開發更加便捷:
@Builder/@BuilderParam:特殊的封裝UI描述的方法,細粒度的封裝和復用UI描述。
@Extend/@Style:擴展內置組件和封裝屬性樣式,更靈活地組合內置組件。
stateStyles:多態樣式,可以依據組件的內部狀態的不同,設置不同樣式。
??4.自定義組件
@Component
struct HelloComponent {
@State message: string = 'Hello, World!';
build() {
// HelloComponent自定義組件組合系統組件Row和Text
Row() {
Text(this.message)
.onClick(() => {
// 狀態變量message的改變驅動UI刷新,UI從'Hello, World!'刷新為'Hello, ArkUI!'
this.message = 'Hello, ArkUI!';
})
}
}
}
@Entry
@Component
struct ParentComponent {
build() {
Column() {
Text('ArkUI message')
HelloComponent({ message: 'Hello, World!' });
Divider()
HelloComponent({ message: '你好!' });
}
}
}
struct:自定義組件基于struct實現,struct + 自定義組件名 +
{…}的組合構成自定義組件,不能有繼承關系。對于struct的實例化,可以省略new。
build()函數:build()函數用于定義自定義組件的聲明式UI描述,自定義組件必須定義build()函數。
@Entry:@Entry裝飾的自定義組件將作為UI頁面的入口。在單個UI頁面中,最多可以使用@Entry裝飾一個自定義組件。@Entry可以接受一個可選的LocalStorage的參數。
??4.1 build()函數規范
1、根節點唯一
@Entry
@Component
struct MyComponent {
build() {
// 根節點唯一且必要,必須為容器組件
Row() {
ChildComponent()
}
}
}
@Component
struct ChildComponent {
build() {
// 根節點唯一且必要,可為非容器組件
Image('test.jpg')
}
}
2、不允許聲明本地變量、打印、作用域
build() {
// 反例:不允許聲明本地變量
let a: number = 1;
// 反例:不允許console.info
console.info('print debug log');
// 反例:不允許本地作用域
{
...
}
}
3、不允許調用沒有用@Builder裝飾的方法,允許系統組件的參數是TS方法的返回值。
@Component
struct ParentComponent {
doSomeCalculations() {
}
calcTextValue(): string {
return 'Hello World';
}
@Builder doSomeRender() {
Text(`Hello World`)
}
build() {
Column() {
// 反例:不能調用沒有用@Builder裝飾的方法
this.doSomeCalculations();
// 正例:可以調用
this.doSomeRender();
// 正例:參數可以為調用TS方法的返回值
Text(this.calcTextValue())
}
}
}
4、不允許switch和表達式
build() {
Column() {
// 反例:不允許使用switch語法
switch (expression) {
case 1:
Text('...')
break;
case 2:
Image('...')
break;
default:
Text('...')
break;
}
// 反例:不允許使用表達式
(this.aVar > 10) ? Text('...') : Image('...')
}
}
??5.頁面和自定義組件生命周期
頁面生命周期,即被@Entry裝飾的組件生命周期,提供以下生命周期接口:
- onPageShow:頁面每次顯示時觸發。
- onPageHide:頁面每次隱藏時觸發一次。
- onBackPress:當用戶點擊返回按鈕時觸發。
組件生命周期,即一般用@Component裝飾的自定義組件的生命周期,提供以下生命周期接口:
- aboutToAppear:組件即將出現時回調該接口,具體時機為在創建自定義組件的新實例后,在執行其build()函數之前執行。
- aboutToDisappear:在自定義組件即將析構銷毀時執行。
// Index.ets
import router from '@ohos.router';
@Entry
@Component
struct MyComponent {
@State showChild: boolean = true;
// 只有被@Entry裝飾的組件才可以調用頁面的生命周期
onPageShow() {
console.info('Index onPageShow');
}
// 只有被@Entry裝飾的組件才可以調用頁面的生命周期
onPageHide() {
console.info('Index onPageHide');
}
// 只有被@Entry裝飾的組件才可以調用頁面的生命周期
onBackPress() {
console.info('Index onBackPress');
}
// 組件生命周期
aboutToAppear() {
console.info('MyComponent aboutToAppear');
}
// 組件生命周期
aboutToDisappear() {
console.info('MyComponent aboutToDisappear');
}
build() {
Column() {
// this.showChild為true,創建Child子組件,執行Child aboutToAppear
if (this.showChild) {
Child()
}
// this.showChild為false,刪除Child子組件,執行Child aboutToDisappear
Button('create or delete Child').onClick(() => {
this.showChild = false;
})
// push到Page2頁面,執行onPageHide
Button('push to next page')
.onClick(() => {
router.pushUrl({ url: 'pages/Page2' });
})
}
}
}
@Component
struct Child {
@State title: string = 'Hello World';
// 組件生命周期
aboutToDisappear() {
console.info('[lifeCycle] Child aboutToDisappear')
}
// 組件生命周期
aboutToAppear() {
console.info('[lifeCycle] Child aboutToAppear')
}
build() {
Text(this.title).fontSize(50).onClick(() => {
this.title = 'Hello ArkUI';
})
}
}
??6.裝飾函數
??6.1 @Builder裝飾器
@Builder主要是定義頁面UI
??6.1.1 裝飾指向
1、自定義組件內自定義構建函數
@Builder MyBuilderFunction(){ ... }
#使用
this.MyBuilderFunction(){ ... }
2、MyGlobalBuilderFunction()
@Builder function MyGlobalBuilderFunction(){ ... }
#使用
MyGlobalBuilderFunction()
??6.1.2 參數傳遞
1、按引用傳遞參數
@Builder function ABuilder($$: { paramA1: string }) {
Row() {
Text(`UseStateVarByReference: ${$$.paramA1} `)
}
}
@Entry
@Component
struct Parent {
@State label: string = 'Hello';
build() {
Column() {
// 在Parent組件中調用ABuilder的時候,將this.label引用傳遞給ABuilder
ABuilder({ paramA1: this.label })
Button('Click me').onClick(() => {
// 點擊“Click me”后,UI從“Hello”刷新為“ArkUI”
this.label = 'ArkUI';
})
}
}
}
2、按值傳遞參數
@Builder function ABuilder(paramA1: string) {
Row() {
Text(`UseStateVarByValue: ${paramA1} `)
}
}
@Entry
@Component
struct Parent {
label: string = 'Hello';
build() {
Column() {
ABuilder(this.label)
}
}
}
??6.2 @BuilderParam裝飾器
@BuilderParam用來裝飾指向@Builder方法的變量,開發者可在初始化自定義組件時對此屬性進行賦值,為自定義組件增加特定的功能。
??6.2.1 裝飾指向
1、本地初始化@BuilderParam
@Builder function GlobalBuilder0() {}
@Component
struct Child {
@Builder doNothingBuilder() {};
@BuilderParam aBuilder0: () => void = this.doNothingBuilder;
@BuilderParam aBuilder1: () => void = GlobalBuilder0;
build(){}
}
2、初始化子組件@BuilderParam
@Component
struct Child {
@BuilderParam aBuilder0: () => void;
build() {
Column() {
this.aBuilder0()
}
}
}
@Entry
@Component
struct Parent {
@Builder componentBuilder() {
Text(`Parent builder `)
}
build() {
Column() {
Child({ aBuilder0: this.componentBuilder })
}
}
}
this都是器其本身,不會存在傳遞。
??6.2.2 使用場景
1、參數化傳遞
@Builder function GlobalBuilder1($$ : {label: string }) {
Text($$.label)
.width(400)
.height(50)
.backgroundColor(Color.Blue)
}
@Component
struct Child {
label: string = 'Child'
// 無參數類,指向的componentBuilder也是無參數類型
@BuilderParam aBuilder0: () => void;
// 有參數類型,指向的GlobalBuilder1也是有參數類型的方法
@BuilderParam aBuilder1: ($$ : { label : string}) => void;
build() {
Column() {
this.aBuilder0()
this.aBuilder1({label: 'global Builder label' } )
}
}
}
@Entry
@Component
struct Parent {
label: string = 'Parent'
@Builder componentBuilder() {
Text(`${this.label}`)
}
build() {
Column() {
this.componentBuilder()
Child({ aBuilder0: this.componentBuilder, aBuilder1: GlobalBuilder1 })
}
}
}
2、尾隨閉包
// xxx.ets
@Component
struct CustomContainer {
@Prop header: string;
@BuilderParam closer: () => void
build() {
Column() {
Text(this.header)
.fontSize(30)
this.closer()
}
}
}
@Builder function specificParam(label1: string, label2: string) {
Column() {
Text(label1)
.fontSize(30)
Text(label2)
.fontSize(30)
}
}
@Entry
@Component
struct CustomContainerUser {
@State text: string = 'header';
build() {
Column() {
// 創建CustomContainer,在創建CustomContainer時,通過其后緊跟一個大括號“{}”形成尾隨閉包
// 作為傳遞給子組件CustomContainer @BuilderParam closer: () => void的參數
CustomContainer({ header: this.text }) {
Column() {
specificParam('testA', 'testB')
}.backgroundColor(Color.Yellow)
.onClick(() => {
this.text = 'changeHeader';
})
}
}
}
}
??6.3 @Styles裝飾器
@Styles裝飾器主要是定義公共樣式
??6.3.1 裝飾指向
1、全局
// 全局
@Styles function functionName() { ... }
// 在組件內
@Component
struct FancyUse {
@Styles fancy() {
.height(100)
}
}
2、組件內
@Component
struct FancyUse {
@State heightValue: number = 100
@Styles fancy() {
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
}
??6.3.2 使用場景
// 定義在全局的@Styles封裝的樣式
@Styles function globalFancy () {
.width(150)
.height(100)
.backgroundColor(Color.Pink)
}
@Entry
@Component
struct FancyUse {
@State heightValue: number = 100
// 定義在組件內的@Styles封裝的樣式
@Styles fancy() {
.width(200)
.height(this.heightValue)
.backgroundColor(Color.Yellow)
.onClick(() => {
this.heightValue = 200
})
}
build() {
Column({ space: 10 }) {
// 使用全局的@Styles封裝的樣式
Text('FancyA')
.globalFancy ()
.fontSize(30)
// 使用組件內的@Styles封裝的樣式
Text('FancyB')
.fancy()
.fontSize(30)
}
}
}
??6.4 @Extend裝飾器
@Extend用于擴展原生組件樣式,作用和@Styles差不多。
??6.4.1 裝飾指向
@Extend僅支持定義在全局,不支持在組件內部定義
1、@Extend支持封裝指定的組件的私有屬性和私有事件
// @Extend(Text)可以支持Text的私有屬性fontColor
@Extend(Text) function fancy () {
.fontColor(Color.Red)
}
// superFancyText可以調用預定義的fancy
@Extend(Text) function superFancyText(size:number) {
.fontSize(size)
.fancy()
}
2、@Extend裝飾的方法支持參數
// xxx.ets
@Extend(Text) function fancy (fontSize: number) {
.fontColor(Color.Red)
.fontSize(fontSize)
}
@Entry
@Component
struct FancyUse {
build() {
Row({ space: 10 }) {
Text('Fancy')
.fancy(16)
Text('Fancy')
.fancy(24)
}
}
}
3、@Extend裝飾的方法的參數可以為function
@Extend(Text) function makeMeClick(onClick: () => void) {
.backgroundColor(Color.Blue)
.onClick(onClick)
}
@Entry
@Component
struct FancyUse {
@State label: string = 'Hello World';
onClickHandler() {
this.label = 'Hello ArkUI';
}
build() {
Row({ space: 10 }) {
Text(`${this.label}`)
.makeMeClick(this.onClickHandler.bind(this))
}
}
}
4、@Extend的參數可以為狀態變量
@Extend(Text) function fancy (fontSize: number) {
.fontColor(Color.Red)
.fontSize(fontSize)
}
@Entry
@Component
struct FancyUse {
@State fontSizeValue: number = 20
build() {
Row({ space: 10 }) {
Text('Fancy')
.fancy(this.fontSizeValue)
.onClick(() => {
this.fontSizeValue = 30
})
}
}
}
??6.4.2 使用場景
@Extend(Text) function fancyText(weightValue: number, color: Color) {
.fontStyle(FontStyle.Italic)
.fontWeight(weightValue)
.backgroundColor(color)
}
@Entry
@Component
struct FancyUse {
@State label: string = 'Hello World'
build() {
Row({ space: 10 }) {
Text(`${this.label}`)
.fancyText(100, Color.Blue)
Text(`${this.label}`)
.fancyText(200, Color.Pink)
Text(`${this.label}`)
.fancyText(300, Color.Orange)
}.margin('20%')
}
}
??7.多態樣式
stateStyles是屬性方法,可以根據UI內部狀態來設置樣式,類似于css偽類,但語法不同。ArkUI提供以下四種狀態:
- focused:獲焦態
- normal:正常態
- pressed:按壓態
- disabled:不可用態
??7.1 基本使用
@Entry
@Component
struct CompWithInlineStateStyles {
@State focusedColor: Color = Color.Red;
normalColor: Color = Color.Green
build() {
Column() {
Button('clickMe').height(100).width(100)
.stateStyles({
normal: {
.backgroundColor(this.normalColor)
},
focused: {
.backgroundColor(this.focusedColor)
}
})
.onClick(() => {
this.focusedColor = Color.Pink
})
.margin('30%')
}
}
}
??7.2 @Styles和stateStyles聯合使用
@Entry
@Component
struct MyComponent {
@Styles normalStyle() {
.backgroundColor(Color.Gray)
}
@Styles pressedStyle() {
.backgroundColor(Color.Red)
}
build() {
Column() {
Text('Text1')
.fontSize(50)
.fontColor(Color.White)
.stateStyles({
normal: this.normalStyle,
pressed: this.pressedStyle,
})
}
}
}
??7.3 stateStyles里使用常規變量和狀態變量
@Entry
@Component
struct CompWithInlineStateStyles {
@State focusedColor: Color = Color.Red;
normalColor: Color = Color.Green
build() {
Button('clickMe').height(100).width(100)
.stateStyles({
normal: {
.backgroundColor(this.normalColor)
},
focused: {
.backgroundColor(this.focusedColor)
}
})
.onClick(() => {
this.focusedColor = Color.Pink
})
.margin('30%')
}
}
總結
以上是生活随笔為你收集整理的鸿蒙HarmonyOS实战-ArkTS语言(基本语法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring事务传播机制解析
- 下一篇: java信息管理系统总结_java实现科