编辑代码

console.log("Hello  world!    - typescript.jsrun.net")


@Provide("DataService")
class DataProvider {
    public getData() {
        return "Data from DataProvider";
    }
}

class DataConsumer {
    @Consume("DataService")
    dataService!: DataProvider;

    public useData() {
        console.log(this.dataService.getData());
    }
}

// 使用示例
const consumer = new DataConsumer();
consumer.useData();  // 输出: Data from DataProvider


class User {
    private _name: string;

    constructor(name: string) {
        this._name = name;
    }

    get name(): string {
        return this._name;
    }

    @Watch("_name", "onNameChanged")
    set name(value: string) {
        this._name = value;
    }

    onNameChanged() {
        console.log(`Name changed to: ${this._name}`);
    }
}

let user = new User("Alice");
user.name = "Bob";  // 控制台将输出: Name changed to: Bob


@Entry
@Component
struct MyComponent {
    // 在这里可以添加属性和方法
}


@Entry
@Component
struct MyComponent {
    // 在这里添加属性

    // build函数用于定义组件的UI布局
    fn build(& self) -> some_ui_type {
        // 返回一个UI元素,例如一个按钮、文本框等
    }
}


interface Builder {
    build: () => void
}


@Entry
@Component
struct MyComponent {
    // 在这里添加属性

    // build函数用于定义组件的UI布局
    fn build(& self) -> some_ui_type {
        // 返回一个UI元素,例如一个按钮、文本框等
    }
}



@Entry
@Component
struct MyComponent {
    // 在这里添加属性
    bt_text: string = 'OK'
    // build函数用于定义组件的UI布局
    build(){
        // 返回一个UI元素,例如一个按钮、文本框等
        Row(){
            Text("Hello")
                .fontSize(50)
            Button(this.bt_text)
                .fontSize(30)
        }
    }
}


Column() {   //列组件
    Text('item 1')
    Divider()
    Text('item 2')
}


Image('https://xxx/test.jpg')



Text("Hello, World!")


Image(this.imagePath)
Image('https://' + this.imageUrl)
Text(`count: ${this.count}`)


Text('test')
    .fontSize(12)


Image('test.jpg')
    .alt('error.jpg')
    .width(100)
    .height(100)


Text('文本')
    .fontSize(this.size)
Image('test.jpg')
    .width(this.count % 2 === 0 ? 50 : 100)
    .height(this.offset + 50)



Text('文本')
    .fontSize(16)
    .fontColor(Color.Red)
    .fontWeight(FontWeight.Bold)

Button('add counter')
    .onClick(() => {
        this.counter += 2
    })



Button('点击加数')
    .onClick(function () {
        this.counter += 1
    }.bind(this))



myClickHandler(): void {
    this.counter += 1
}

...

Button('点击加数')
    .onClick(this.myClickHandler)




Column() {
    Text('文本')
        .fontSize(100)
    Divider()
    Text(this.myText)
        .fontSize(100)
        .fontColor(Color.Red)
}



Column() {
    Row() {
        Image('test1.jpg')
            .width(100)
            .height(100)
        Button('click +1')
            .onClick(() => {
                console.info('+1 clicked!')
            })
    }

    Divider()
    Row() {
        Image('test2.jpg')
            .width(100)
            .height(100)
        Button('click +2')
            .onClick(() => {
                console.info('+2 clicked!')
            })
    }

    Divider()
    Row() {
        Image('test3.jpg')
            .width(100)
            .height(100)
        Button('click +3')
            .onClick(() => {
                console.info('+3 clicked!')
            })
    }
}

//使用方法
@Builder MyBuilderFunction(){ ... }

//调用方法
this.MyBuilderFunction()

//定义的语法
@Builder function MyGlobalBuilderFunction() { ... }

//使用方法
MyGlobalBuilderFunction()



overBuilder($$ : { paramA1: string, paramB1: string });


@Builder function overBuilder($$: { paramA1: string }) {
    Row() {
        Text(`UseStateVarByReference: ${$$.paramA1} `)
    }
}
@Entry
@Component
struct Parent {
    @State label: string = 'Hello';
    build() {
        Column() {
            // 在Parent组件中调用overBuilder的时候,将this.label引用传递给overBuilder
            overBuilder({ paramA1: this.label })
            Button('Click me').onClick(() => {
                // 点击“Click me”后,UI从“Hello”刷新为“ArkUI”
                this.label = 'ArkUI';
            })
        }
    }
}



@Builder function overBuilder(paramA1: string) {
    Row() {
        Text(`UseStateVarByValue: ${paramA1} `)
    }
}
@Entry
@Component
struct Parent {
    @State label: string = 'Hello';
    build() {
        Column() {
            overBuilder(this.label)
        }
    }
}



// 全局
@Styles function functionName() { ... }

// 在组件内
@Component
struct FancyUse {
    @Styles fancy() {
    .height(100)
    }
}


@Component
struct FancyUse {
    @State heightValue: number = 100
    @Styles fancy() {
    .height(this.heightValue)
            .backgroundColor(Color.Yellow)
            .onClick(() => {
                this.heightValue = 200
            })
    }
}


@Extend(UIComponentName) function functionName { ... }


// @Extend(Text)可以支持Text的私有属性fontColor
@Extend(Text) function fancy() {
  .fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) function superFancyText(size: number) {
    .fontSize(size)
        .fancy()
}




@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)
        }
    }
}



@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))
        }
    }
}


@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
                })
        }
    }
}




@Component
struct MyComponent {
  private countDownFrom: number = 0;
  private color: Color = Color.Blue;

    build() {
    }
}

@Entry
@Component
struct ParentComponent {
  private someColor: Color = Color.Pink;

    build() {
        Column() {
            // 创建MyComponent实例,并将创建MyComponent成员变量countDownFrom初始化为10,将成员变量color初始化为this.someColor
            MyComponent({ countDownFrom: 10, color: this.someColor })
        }
    }
}


@Entry
@Component
struct MyComponent {
    build() {
        // 根节点唯一且必要,必须为容器组件
        Row() {
            ChildComponent()
        }
    }
}

@Component
struct ChildComponent {
    build() {
        // 根节点唯一且必要,可为非容器组件
        Image('test.jpg')
    }
}


build() {
    // 反例:不允许声明本地变量
    let a: number = 1;
}


build() {
    // 反例:不允许console.info
    console.info('print debug log');
}



build() {
    // 反例:不允许本地作用域
    {
    ...
    }
}



@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())
        }
    }
}


build() {
    Column() {
        // 反例:不允许使用switch语法
        switch (expression) {
            case 1:
                Text('...')
                break;
            case 2:
                Image('...')
                break;
            default:
                Text('...')
                break;
        }
    }
}


build() {
    Column() {
        // 反例:不允许使用表达式
        (this.aVar > 10) ? Text('...') : Image('...')
    }
}



@Component
struct MyComponent2 {
    build() {
        Button(`Hello World`)
    }
}

@Entry
@Component
struct MyComponent {
    build() {
        Row() {
            MyComponent2()
                .width(200)
                .height(300)
                .backgroundColor(Color.Red)
        }
    }
}


// xxx.ets
@Component
struct CompB {
    @State CompValue: string = ''

    aboutToAppear() {
        console.info('CompB aboutToAppear.')
    }

    aboutToDisappear() {
        console.info('CompB aboutToDisappear.')
    }

    build() {
        Column() {
            Button(this.CompValue)
                .margin(5)
        }
    }
}

@Entry
@Component
struct CompA {
    size1: number = 100
    @State CompValue1: string = "Hello,CompValue1"
    @State CompValue2: string = "Hello,CompValue2"
    @State CompValue3: string = "Hello,CompValue3"

    // @Builder装饰的函数CompC内使用自定义组件CompB
    @Builder CompC(value: string) {
        CompB({ CompValue: value })
    }

    @Builder SquareText(label: string) {
        Text(label)
            .fontSize(18)
            .width(1 * this.size1)
            .height(1 * this.size1)
    }

    // @Builder装饰的函数RowOfSquareTexts内使用@Builder装饰的函数SquareText
    @Builder RowOfSquareTexts(label1: string, label2: string) {
        Row() {
            this.SquareText(label1)
            this.SquareText(label2)
        }
    .width(2 * this.size1)
            .height(1 * this.size1)
    }

    build() {
        Column() {
            Row() {
                this.SquareText("A")
                this.SquareText("B")
            }
      .width(2 * this.size1)
                .height(1 * this.size1)

            this.RowOfSquareTexts("C", "D")
            Column() {
                // 使用三次@Builder装饰的自定义组件
                this.CompC(this.CompValue1)
                this.CompC(this.CompValue2)
                this.CompC(this.CompValue3)
            }
      .width(2 * this.size1)
                .height(2 * this.size1)
        }
    .width(2 * this.size1)
            .height(2 * this.size1)
    }
}




// xxx.ets
@Component
struct CustomContainer {
    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({
                header: this.text,
            }) {
                Column() {
                    specificParam('testA', 'testB')
                }.backgroundColor(Color.Yellow)
                    .onClick(() => {
                        this.text = 'changeHeader'
                    })
            }
        }
    }
}



// xxx.ets
@Styles function globalFancy() {
  .width(150)
        .height(100)
        .backgroundColor(Color.Pink)
}

@Entry
@Component
struct FancyUse {
    @Styles componentFancy() {
    .width(100)
            .height(200)
            .backgroundColor(Color.Yellow)
    }

    build() {
        Column({ space: 10 }) {
            Text('FancyA')
                .globalFancy()
                .fontSize(30)
            Text('FancyB')
                .globalFancy()
                .fontSize(20)
            Text('FancyC')
                .componentFancy()
                .fontSize(30)
            Text('FancyD')
                .componentFancy()
                .fontSize(20)
        }
    }
}




// xxx.ets
@Styles function globalFancy() {
  .width(120)
        .height(120)
        .backgroundColor(Color.Green)
}

@Entry
@Component
struct FancyUse {
    @Styles componentFancy() {
    .width(80)
            .height(80)
            .backgroundColor(Color.Red)
    }

    build() {
        Row({ space: 10 }) {
            Button('Fancy')
                .stateStyles({
                    normal: {
            .width(100)
            .height(100)
            .backgroundColor(Color.Blue)
                    },
                    disabled: this.componentFancy,
                    pressed: globalFancy
                })
        }
    }
}



// xxx.ets
@Extend(Text) function fancy(fontSize: number) {
  .fontColor(Color.Red)
        .fontSize(fontSize)
        .fontStyle(FontStyle.Italic)
        .fontWeight(600)
}

@Entry
@Component
struct FancyUse {
    build() {
        Row({ space: 10 }) {
            Text("Fancy")
                .fancy(16)
            Text("Fancy")
                .fancy(24)
            Text("Fancy")
                .fancy(32)
        }
    }
}



// xxx.ets
@CustomDialog
struct DialogExample {
    controller: CustomDialogController
    action: () => void

        build() {
        Row() {
            Button('Close CustomDialog')
                .onClick(() => {
                    this.controller.close()
                    this.action()
                })
        }.padding(20)
    }
}

@Entry
@Component
struct CustomDialogUser {
    dialogController: CustomDialogController = new CustomDialogController({
        builder: DialogExample({ action: this.onAccept }),
        cancel: this.existApp,
        autoCancel: true
    });

    onAccept() {
        console.info('onAccept');
    }

    existApp() {
        console.info('Cancel dialog!');
    }

    build() {
        Column() {
            Button('Click to open Dialog')
                .onClick(() => {
                    this.dialogController.open()
                })
        }
    }
}


Column() {
    if (this.count < 0) {
        Text('count is negative').fontSize(14)
    } else if (this.count % 2 === 0) {
        Text('count is even').fontSize(14)
    } else {
        Text('count is odd').fontSize(14)
    }
}


// xxx.ets
@Entry
@Component
struct MyComponent {
    @State arr: number[] = [10, 20, 30]

    build() {
        Column({ space: 5 }) {
            Button('Reverse Array')
                .onClick(() => {
                    this.arr.reverse()
                })

            ForEach(this.arr, (item: number) => {
                Text(`item value: ${item}`).fontSize(18)
                Divider().strokeWidth(2)
            }, (item: number) => item.toString())
        }
    }
}


// xxx.ets
class BasicDataSource implements IDataSource {
    private listeners: DataChangeListener[] = []

    public totalCount(): number {
        return 0
    }

    public getData(index: number): any {
        return undefined
    }

    registerDataChangeListener(listener: DataChangeListener): void {
        if (this.listeners.indexOf(listener) < 0) {
            console.info('add listener')
            this.listeners.push(listener)
        }
    }

    unregisterDataChangeListener(listener: DataChangeListener): void {
        const pos = this.listeners.indexOf(listener);
        if (pos >= 0) {
            console.info('remove listener')
            this.listeners.splice(pos, 1)
        }
    }

    notifyDataReload(): void {
        this.listeners.forEach(listener => {
            listener.onDataReloaded()
        })
    }

    notifyDataAdd(index: number): void {
        this.listeners.forEach(listener => {
            listener.onDataAdd(index)
        })
    }

    notifyDataChange(index: number): void {
        this.listeners.forEach(listener => {
            listener.onDataChange(index)
        })
    }

    notifyDataDelete(index: number): void {
        this.listeners.forEach(listener => {
            listener.onDataDelete(index)
        })
    }

    notifyDataMove(from: number, to: number): void {
        this.listeners.forEach(listener => {
            listener.onDataMove(from, to)
        })
    }
}

class MyDataSource extends BasicDataSource {
    // 初始化数据列表
    private dataArray: string[] = ['/path/image0.png', '/path/image1.png', '/path/image2.png', '/path/image3.png']

    public totalCount(): number {
        return this.dataArray.length
    }

    public getData(index: number): any {
        return this.dataArray[index]
    }

    public addData(index: number, data: string): void {
        this.dataArray.splice(index, 0, data)
        this.notifyDataAdd(index)
    }

    public pushData(data: string): void {
        this.dataArray.push(data)
        this.notifyDataAdd(this.dataArray.length - 1)
    }
}

@Entry
@Component
struct MyComponent {
  private data: MyDataSource = new MyDataSource()

    build() {
        List({ space: 3 }) {
            LazyForEach(this.data, (item: string) => {
                ListItem() {
                    Row() {
                        Image(item).width(50).height(50)
                        Text(item).fontSize(20).margin({ left: 10 })
                    }.margin({ left: 10, right: 10 })
                }
        .onClick(() => {
                    // 每点击一次列表项,数据增加一项
                    this.data.pushData('/path/image' + this.data.totalCount() + '.png')
                })
            }, item => item)
        }
    }
}




LazyForEach(
    dataSource: IDataSource,
    itemGenerator: (item: any) => void,
    keyGenerator ?: (item: any) => string
): void

    interface IDataSource {
    totalCount(): number;
    getData(index: number): any;
    registerDataChangeListener(listener: DataChangeListener): void;
    unregisterDataChangeListener(listener: DataChangeListener): void;
}

interface DataChangeListener {
    onDataReloaded(): void;
    onDataAdd(index: number): void;
    onDataMove(from: number, to: number): void;
    onDataDelete(index: number): void;
    onDataChange(index: number): void;
}


LazyForEach(dataSource,
    item => Text(`${item.i}. item.data.label`)),
    item => item.data.id.toString())



ForEach(
    arr: any[],
    itemGenerator: (item: any, index?: number) => void,
    keyGenerator ?: (item: any, index?: number) => string
)


for (let i = 0; i < 10; i++) {
    console.log(i);
}


let i = 0;
while (i < 10) {
    console.log(i);
    i++;
}


let i = 0;
do {
    console.log(i);
    i++;
} while (i < 10);


const obj = { a: 1, b: 2, c: 3 };
for (let prop in obj) {
    console.log(`${prop}: ${obj[prop]}`);
}


const arr = [1, 2, 3];
for (let item of arr) {
    console.log(item);
}

let sum: number = 0;

for (let i: number = 1; i <= 10; i++) {
    if (i === 5) {
        break; // 当 i 等于 5 时终止循环
    }

    if (i === 3) {
        continue; // 当 i 等于 3 时跳过当前迭代,继续下一次迭代
    }

    sum += i;
}

console.log(sum); // 输出结果为 12




@Entry
@Component
struct Index {
    @State message: string = '循环渲染'
    //创建一个景色数组
    @State scenery: Array < string > =['江上', '清风', '山间', '明月', '造物者']

    build() {
        Row() {
            Column() {
                Text(this.message)
                    .fontSize(50)
                    .fontWeight(FontWeight.Bold)
                Divider()

                //使用ForEach渲染:遍历每一个数据并用Text呈现在UI界面上
                //第一个参数为需要遍历的数组,第二参数为对每个遍历元素进行操作的函数,第三参数为返回的每一个元素索引(唯一值)
                ForEach(this.scenery, (item1) => {
                    Text(item1)
                        .fontSize(30)
                        .fontStyle(FontStyle.Italic)
                }, (item2) => {
                    return item2
                })

            }
      .width('100%')
        }
    .height('100%')
    }
}




@Entry
@Component
struct Index {
    @State message: string = '循环渲染'
    //创建一个对象数组
    @State obj: object[] = [
        {
            id: '001',
            name: '江上',
            age: 16
        },
        {
            id: '002',
            name: '明月',
            age: 25
        },
        {
            id: '003',
            name: '造物者',
            age: 35
        }
    ]

    build() {
        Row() {
            Column() {
                Text(this.message)
                    .fontSize(50)
                    .fontWeight(FontWeight.Bold)
                Divider()

                //使用ForEach渲染:遍历每一个数据并用Text呈现在UI界面上
                //第一个参数为需要遍历的数组,第二参数为对每个遍历元素进行操作的函数,第三参数为返回的每一个元素索引(唯一值)
                //此处总共遍历3个项目,每一个项目下面都有三个元素:id,name,age
                ForEach(this.obj, (item1) => {
                    Text(`${item1.id}=> ${item1.name}=> ${item1.age} `)
                        .fontSize(30)
                        .fontStyle(FontStyle.Italic)
                }, (item2) => {
                    return item2.id
                    //错误示范:return item2
                })

            }
      .width('100%')
        }
    .height('100%')
    }
}



array.forEach(callbackFn(currentValue, index, array))

const numbers = [1, 2, 3, 4, 5];
numbers.forEach(element => {
    console.log(element);
});


@Component
struct MyComponent {
    @State count: number = 0;
  private increaseBy: number = 1;

    build() {
    }
}

@Component
struct Parent {
    build() {
        Column() {
            // 从父组件初始化,覆盖本地定义的默认值
            MyComponent({ count: 1, increaseBy: 2 })
        }
    }
}


@Entry
@Component
struct MyComponent {
    @State count: number = 0;

    build() {
        Button(`click times: ${this.count}`)
            .onClick(() => {
                this.count += 1;
            })
    }
}



class Model {
    public value: string;

    constructor(value: string) {
        this.value = value;
    }
}

@Entry
@Component
struct EntryComponent {
    build() {
        Column() {
            // 此处指定的参数都将在初始渲染时覆盖本地定义的默认值,并不是所有的参数都需要从父组件初始化
            MyComponent({ count: 1, increaseBy: 2 })
                .width(300)
            MyComponent({ title: new Model('Hello World 2'), count: 7 })
        }
    }
}

@Component
struct MyComponent {
    @State title: Model = new Model('Hello World');
    @State count: number = 0;
  private increaseBy: number = 1;

    build() {
        Column() {
            Text(`${this.title.value}`)
                .margin(10)
            Button(`Click to change title`)
                .onClick(() => {
                    // @State变量的更新将触发上面的Text组件内容更新
                    this.title.value = this.title.value === 'Hello ArkUI' ? 'Hello World' : 'Hello ArkUI';
                })
                .width(300)
                .margin(10)

            Button(`Click to increase count = ${this.count}`)
                .onClick(() => {
                    // @State变量的更新将触发该Button组件的内容更新
                    this.count += this.increaseBy;
                })
                .width(300)
                .margin(10)
        }
    }
}


@State title: Model = new Model('Hello World');
@State count: number = 0;

MyComponent({ count: 1, increaseBy: 2 })


@Component
struct CountDownComponent {
    @Prop count: number;
    costOfOneAttempt: number = 1;

    build() {
        Column() {
            if (this.count > 0) {
                Text(`You have ${this.count} Nuggets left`)
            } else {
                Text('Game over!')
            }
            // @Prop装饰的变量不会同步给父组件
            Button(`Try again`).onClick(() => {
                this.count -= this.costOfOneAttempt;
            })
        }
    }
}

@Entry
@Component
struct ParentComponent {
    @State countDownStartValue: number = 10;

    build() {
        Column() {
            Text(`Grant ${this.countDownStartValue} nuggets to play.`)
            // 父组件的数据源的修改会同步给子组件
            Button(`+1 - Nuggets in New Game`).onClick(() => {
                this.countDownStartValue += 1;
            })
            // 父组件的修改会同步给子组件
            Button(`-1  - Nuggets in New Game`).onClick(() => {
                this.countDownStartValue -= 1;
            })

            CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 })
        }
    }
}



@Component
struct Child {
    @Prop value: number;

    build() {
        Text(`${this.value}`)
            .fontSize(50)
            .onClick(() => { this.value++ })
    }
}

@Entry
@Component
struct Index {
    @State arr: number[] = [1, 2, 3];

    build() {
        Row() {
            Column() {
                Child({ value: this.arr[0] })
                Child({ value: this.arr[1] })
                Child({ value: this.arr[2] })

                Divider().height(5)

                ForEach(this.arr,
                    item => {
                        Child({ 'value': item } as Record<string, number>)
                    },
                    item => item.toString()
                )
                Text('replace entire arr')
                    .fontSize(50)
                    .onClick(() => {
                        // 两个数组都包含项“3”。
                        this.arr = this.arr[0] == 1 ? [3, 4, 5] : [1, 2, 3];
                    })
            }
        }
    }
}



class Book {
    public title: string;
    public pages: number;
    public readIt: boolean = false;

    constructor(title: string, pages: number) {
        this.title = title;
        this.pages = pages;
    }
}

@Component
struct ReaderComp {
    @Prop title: string;
    @Prop readIt: boolean;

    build() {
        Row() {
            Text(this.title)
            Text(`... ${this.readIt ? 'I have read' : 'I have not read it'}`)
                .onClick(() => this.readIt = true)
        }
    }
}

@Entry
@Component
struct Library {
    @State book: Book = new Book('100 secrets of C++', 765);

    build() {
        Column() {
            ReaderComp({ title: this.book.title, readIt: this.book.readIt })
            ReaderComp({ title: this.book.title, readIt: this.book.readIt })
        }
    }
}









@Component
struct Child {
    @Link items: number[];

    build() {
        Column() {
            Button(`Button1: push`)
                .margin(12)
                .width(312)
                .height(40)
                .fontColor('#FFFFFF,90%')
                .onClick(() => {
                    this.items.push(this.items.length + 1);
                })
            Button(`Button2: replace whole item`)
                .margin(12)
                .width(312)
                .height(40)
                .fontColor('#FFFFFF,90%')
                .onClick(() => {
                    this.items = [100, 200, 300];
                })
        }
    }
}

@Entry
@Component
struct Parent {
    @State arr: number[] = [1, 2, 3];

    build() {
        Column() {
            Child({ items: $arr })
                .margin(12)
            ForEach(this.arr,
                (item: number) => {
                    Button(`${item}`)
                        .margin(12)
                        .width(312)
                        .height(40)
                        .backgroundColor('#11a2a2a2')
                        .fontColor('#e6000000')
                },
                (item: ForEachInterface) => item.toString()
            )
        }
    }
}




// 通过相同的变量名绑定
@Provide a: number = 0;
@Consume a: number;

// 通过相同的变量别名绑定
@Provide('a') b: number = 0;
@Consume('a') c: number;



@Component
struct CompD {
    // @Consume装饰的变量通过相同的属性名绑定其祖先组件CompA内的@Provide装饰的变量
    @Consume reviewVotes: number;

    build() {
        Column() {
            Text(`reviewVotes(${this.reviewVotes})`)
            Button(`reviewVotes(${this.reviewVotes}), give +1`)
                .onClick(() => this.reviewVotes += 1)
        }
    .width('50%')
    }
}

@Component
struct CompC {
    build() {
        Row({ space: 5 }) {
            CompD()
            CompD()
        }
    }
}

@Component
struct CompB {
    build() {
        CompC()
    }
}

@Entry
@Component
struct CompA {
    // @Provide装饰的变量reviewVotes由入口组件CompA提供其后代组件
    @Provide reviewVotes: number = 0;

    build() {
        Column() {
            Button(`reviewVotes(${this.reviewVotes}), give +1`)
                .onClick(() => this.reviewVotes += 1)
            CompB()
        }
    }
}







@ObjectLink b: ClassB

// 赋值变化可以被观察到
this.b.a = new ClassA(5)
this.b.b = 5

// ClassA没有被@Observed装饰,其属性的变化观察不到
this.b.a.c = 5








@Component
struct ViewA {
    label: string = 'ViewA1';
    @ObjectLink a: ClassA;

    build() {
        Row() {
            Button(`ViewA [${this.label}] this.a.c=${this.a.c} +1`)
                .onClick(() => {
                    this.a.c += 1;
                })
        }
    }
}

@Entry
@Component
struct ViewB {
    @State b: ClassB = new ClassB(new ClassA(0));

    build() {
        Column() {
            // in low version,DevEco may throw a warning,but it does not matter.
            // you can still compile and run.
            ViewA({ label: 'ViewA #1', a: this.b.a })
            ViewA({ label: 'ViewA #2', a: this.b.a })

            Button(`ViewB: this.b.a.c+= 1`)
                .onClick(() => {
                    this.b.a.c += 1;
                })
            Button(`ViewB: this.b.a = new ClassA(0)`)
                .onClick(() => {
                    this.b.a = new ClassA(0);
                })
            Button(`ViewB: this.b = new ClassB(ClassA(0))`)
                .onClick(() => {
                    this.b = new ClassB(new ClassA(0));
                })
        }
    }
}





let NextID: number = 1;

@Observed
class ClassA {
    public id: number;
    public c: number;

    constructor(c: number) {
        this.id = NextID++;
        this.c = c;
    }
}
@Component
struct ViewA {
    // 子组件ViewA的@ObjectLink的类型是ClassA
    @ObjectLink a: ClassA;
    label: string = 'ViewA1';

    build() {
        Row() {
            Button(`ViewA [${this.label}] this.a.c = ${this.a.c} +1`)
                .onClick(() => {
                    this.a.c += 1;
                })
        }
    }
}

@Entry
@Component
struct ViewB {
    // ViewB中有@State装饰的ClassA[]
    @State arrA: ClassA[] = [new ClassA(0), new ClassA(0)];

    build() {
        Column() {
            ForEach(this.arrA,
                (item) => {
                    ViewA({ label: `#${item.id}`, a: item })
                },
                (item) => item.id.toString()
            )
            // 使用@State装饰的数组的数组项初始化@ObjectLink,其中数组项是被@Observed装饰的ClassA的实例
            ViewA({ label: `ViewA this.arrA[first]`, a: this.arrA[0] })
            ViewA({ label: `ViewA this.arrA[last]`, a: this.arrA[this.arrA.length - 1] })

            Button(`ViewB: reset array`)
                .onClick(() => {
                    this.arrA = [new ClassA(0), new ClassA(0)];
                })
            Button(`ViewB: push`)
                .onClick(() => {
                    this.arrA.push(new ClassA(0))
                })
            Button(`ViewB: shift`)
                .onClick(() => {
                    this.arrA.shift()
                })
            Button(`ViewB: chg item property in middle`)
                .onClick(() => {
                    this.arrA[Math.floor(this.arrA.length / 2)].c = 10;
                })
            Button(`ViewB: chg item property in middle`)
                .onClick(() => {
                    this.arrA[Math.floor(this.arrA.length / 2)] = new ClassA(11);
                })
        }
    }
}



@Observed
class StringArray extends Array<String> {
}




@Observed
class StringArray extends Array<String> {
}

@Component
struct ItemPage {
    @ObjectLink itemArr: StringArray;

    build() {
        Row() {
            Text('ItemPage')
                .width(100).height(100)

            ForEach(this.itemArr,
                item => {
                    Text(item)
                        .width(100).height(100)
                },
                item => item
            )
        }
    }
}

@Entry
@Component
struct IndexPage {
    @State arr: Array < StringArray > =[new StringArray(), new StringArray(), new StringArray()];

    build() {
        Column() {
            ItemPage({ itemArr: this.arr[0] })
            ItemPage({ itemArr: this.arr[1] })
            ItemPage({ itemArr: this.arr[2] })

            Divider()

            ForEach(this.arr,
                itemArr => {
                    ItemPage({ itemArr: itemArr })
                },
                itemArr => itemArr[0]
            )

            Divider()

            Button('update')
                .onClick(() => {
                    console.error('Update all items in arr');
                    if (this.arr[0][0] !== undefined) {
                        // 正常情况下需要有一个真实的ID来与ForEach一起使用,但此处没有
                        // 因此需要确保推送的字符串是唯一的。
                        this.arr[0].push(`${this.arr[0].slice(-1).pop()}${this.arr[0].slice(-1).pop()}`);
                        this.arr[1].push(`${this.arr[1].slice(-1).pop()}${this.arr[1].slice(-1).pop()}`);
                        this.arr[2].push(`${this.arr[2].slice(-1).pop()}${this.arr[2].slice(-1).pop()}`);
                    } else {
                        this.arr[0].push('Hello');
                        this.arr[1].push('World');
                        this.arr[2].push('!');
                    }
                })
        }
    }
}


let storage = new LocalStorage({ 'PropA': 47 }); // 创建新实例并使用给定对象初始化
let propA = storage.get('PropA') // propA == 47
let link1 = storage.link('PropA'); // link1.get() == 47
let link2 = storage.link('PropA'); // link2.get() == 47
let prop = storage.prop('PropA'); // prop.get() = 47
link1.set(48); // two-way sync: link1.get() == link2.get() == prop.get() == 48
prop.set(1); // one-way sync: prop.get()=1; but link1.get() == link2.get() == 48
link1.set(49); // two-way sync: link1.get() == link2.get() == prop.get() == 49




// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });

@Component
struct Child {
    // @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
    @LocalStorageLink('PropA') storLink2: number = 1;

    build() {
        Button(`Child from LocalStorage ${this.storLink2}`)
            // 更改将同步至LocalStorage中的'PropA'以及Parent.storLink1
            .onClick(() => this.storLink2 += 1)
    }
}
// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct CompA {
    // @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
    @LocalStorageLink('PropA') storLink1: number = 1;

    build() {
        Column({ space: 15 }) {
            Button(`Parent from LocalStorage ${this.storLink1}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already
                .onClick(() => this.storLink1 += 1)
            // @Component子组件自动获得对CompA LocalStorage实例的访问权限。
            Child()
        }
    }
}



// 创建新实例并使用给定对象初始化
let storage = new LocalStorage({ 'PropA': 47 });
// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct CompA {
    // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
    @LocalStorageProp('PropA') storProp1: number = 1;

    build() {
        Column({ space: 15 }) {
            // 点击后从47开始加1,只改变当前组件显示的storProp1,不会同步到LocalStorage中
            Button(`Parent from LocalStorage ${this.storProp1}`)
                .onClick(() => this.storProp1 += 1)
            Child()
        }
    }
}

@Component
struct Child {
    // @LocalStorageProp变量装饰器与LocalStorage中的'PropA'属性建立单向绑定
    @LocalStorageProp('PropA') storProp2: number = 2;

    build() {
        Column({ space: 15 }) {
            // 当CompA改变时,当前storProp2不会改变,显示47
            Text(`Parent from LocalStorage ${this.storProp2}`)
        }
    }
}



// 构造LocalStorage实例
let storage = new LocalStorage({ 'PropA': 47 });
// 调用link(api9以上)接口构造'PropA'的双向同步数据,linkToPropA 是全局变量
let linkToPropA = storage.link('PropA');

@Entry(storage)
@Component
struct CompA {

    // @LocalStorageLink('PropA')在CompA自定义组件中创建'PropA'的双向同步数据,初始值为47,因为在构造LocalStorage已经给“PropA”设置47
    @LocalStorageLink('PropA') storLink: number = 1;

    build() {
        Column() {
            Text(`incr @LocalStorageLink variable`)
                // 点击“incr @LocalStorageLink variable”,this.storLink加1,改变同步回storage,全局变量linkToPropA也会同步改变

                .onClick(() => this.storLink += 1)

            // 并不建议在组件内使用全局变量linkToPropA.get(),因为可能会有生命周期不同引起的错误。
            Text(`@LocalStorageLink: ${this.storLink} - linkToPropA: ${linkToPropA.get()}`)
        }
    }
}



let storage = new LocalStorage({ countStorage: 1 });

@Component
struct Child {
    // 子组件实例的名字
    label: string = 'no name';
    // 和LocalStorage中“countStorage”的双向绑定数据
    @LocalStorageLink('countStorage') playCountLink: number = 0;

    build() {
        Row() {
            Text(this.label)
                .width(50).height(60).fontSize(12)
            Text(`playCountLink ${this.playCountLink}: inc by 1`)
                .onClick(() => {
                    this.playCountLink += 1;
                })
                .width(200).height(60).fontSize(12)
        }.width(300).height(60)
    }
}

@Entry(storage)
@Component
struct Parent {
    @LocalStorageLink('countStorage') playCount: number = 0;

    build() {
        Column() {
            Row() {
                Text('Parent')
                    .width(50).height(60).fontSize(12)
                Text(`playCount ${this.playCount} dec by 1`)
                    .onClick(() => {
                        this.playCount -= 1;
                    })
                    .width(250).height(60).fontSize(12)
            }.width(300).height(60)

            Row() {
                Text('LocalStorage')
                    .width(50).height(60).fontSize(12)
                Text(`countStorage ${this.playCount} incr by 1`)
                    .onClick(() => {
                        storage.set<number>('countStorage', 1 + storage.get<number>('countStorage'));
                    })
                    .width(250).height(60).fontSize(12)
            }.width(300).height(60)

            Child({ label: 'ChildA' })
            Child({ label: 'ChildB' })

            Text(`playCount in LocalStorage for debug ${storage.get<number>('countStorage')}`)
                .width(300).height(60).fontSize(12)
        }
    }
}