HarmonyOS鸿蒙-@State@Prop装饰器限制条件

一、组件Components级别的状态管理:

@State组件内状态限制条件

1.@State装饰的变量必须初始化,否则编译期会报错。

TypeScript 复制代码
// 错误写法,编译报错
@State count: number;

// 正确写法
@State count: number = 10;

2.嵌套属性的赋值观察不到。

TypeScript 复制代码
// 嵌套的属性赋值观察不到
this.title.name.value = 'ArkUI';

3.数组项中属性的赋值观察不到。

TypeScript 复制代码
// 嵌套的属性赋值观察不到
this.title[0].value = 6;

4.@State不支持装饰Function类型的变量,框架会抛出运行时错误。

5.@State装饰简单使用场景,执行Button组件的更新方法,实现按需刷新。

TypeScript 复制代码
@Entry
@Component
struct MyComponent {
  @State count: number = 0;

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

6.@State支持联合类型和undefined和null

TypeScript 复制代码
  @State count: number | undefined = 0;

二、@Prop装饰器:父子单向同步 限制条件

1.概述

@Prop装饰的变量和父组件建立单向的同步关系:

  • @Prop变量允许在本地修改,但修改后的变化不会同步回父组件。

  • 当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。

2.限制条件

  • @Prop装饰变量时会进行深拷贝,在拷贝的过程中除了基本类型、Map、Set、Date、Array外,都会丢失类型。例如PixelMap等通过NAPI提供的复杂类型,由于有部分实现在Native侧,因此无法在ArkTS侧通过深拷贝获得完整的数据。

  • @Prop装饰器不能在@Entry装饰的自定义组件中使用。

3.当使用undefined和null的时候,建议显式指定类型,

TypeScript 复制代码
遵循TypeScript类型校验,比如:
@Prop a : string | undefined = undefined  是推荐的,
@Prop a: string = undefined    不推荐

4.嵌套传递层数,更建议使用@ObjectLink

TypeScript 复制代码
在组件复用场景,建议@Prop深度嵌套数据不要超过5层,
嵌套太多会导致深拷贝占用的空间过大以及GarbageCollection(垃圾回收),
引起性能问题,此时更建议使用@ObjectLink。

5.@Prop装饰的变量是私有的,只能在组件内访问。

  1. @Prop 观察不到第二层的变化, 对于这种嵌套场景,如果class是被@Observed装饰的,可以观察到class属性的变化,@Prop嵌套场景
TypeScript 复制代码
@Prop title: Model;
// 可以观察到第一层的变化
this.title.value = 'Hi';
// 观察不到第二层的变化
this.title.info.value = 'ArkUI';

7.@Prop装饰的数据更新依赖其所属自定义组件的重新渲染,所以在应用进入后台后,@Prop无法刷新,推荐使用@Link代替。

8.@Prop装饰状态变量未初始化错误

@Prop需要被初始化,如果没有进行本地初始化的,则必须通过父组件进行初始化。

如果进行了本地初始化,那么是可以不通过父组件进行初始化的。

PS: 看代码中注释部分

TypeScript 复制代码
@Observed
class Commodity {
  public price: number = 0;

  constructor(price: number) {
    this.price = price;
  }
}

@Component
struct PropChild1 {
  @Prop fruit: Commodity; // 未进行本地初始化

  build() {
    Text(`PropChild1 fruit ${this.fruit.price}`)
      .onClick(() => {
        this.fruit.price += 1;
      })
  }
}

@Component
struct PropChild2 {
  @Prop fruit: Commodity = new Commodity(1); // 进行本地初始化

  build() {
    Text(`PropChild2 fruit ${this.fruit.price}`)
      .onClick(() => {
        this.fruit.price += 1;
      })
  }
}

@Entry
@Component
struct Parent {
  @State fruit: Commodity[] = [new Commodity(1)];

  build() {
    Column() {
      Text(`Parent fruit ${this.fruit[0].price}`)
        .onClick(() => {
          this.fruit[0].price += 1;
        })

      // @PropChild1本地没有初始化,必须从父组件初始化
      PropChild1({ fruit: this.fruit[0] })
      // @PropChild2本地进行了初始化,可以不从父组件初始化,也可以从父组件初始化
      PropChild2()
      PropChild2({ fruit: this.fruit[0] })
    }
  }
}

9.使用a.b(this.object)形式调用,不会触发UI刷新

PS: 看代码中注释部分

TypeScript 复制代码
class Score {
  value: number;
  constructor(value: number) {
    this.value = value;
  }

  static changeScore1(score:Score) {
    score.value += 1;
  }
}

@Entry
@Component
struct Parent {
  @State score: Score = new Score(1);

  build() {
    Column({space:8}) {
      Text(`The value in Parent is ${this.score.value}.`)
        .fontSize(30)
        .fontColor(Color.Red)
      Child({ score: this.score })
    }
    .width('100%')
    .height('100%')
  }
}

@Component
struct Child {
  @Prop score: Score;

  changeScore2(score:Score) {
    score.value += 2;
  }

  build() {
    Column({space:8}) {
      Text(`The value in Child is ${this.score.value}.`)
        .fontSize(30)
      Button(`changeScore1`)
        .onClick(()=>{

          // 通过静态方法调用,无法触发UI刷新
          // Score.changeScore1(this.score);   -- 不推荐

          // 通过赋值添加 Proxy 代理  -- 推荐
          let score1 = this.score;
          Score.changeScore1(score1); 
        })
      Button(`changeScore2`)
        .onClick(()=>{

          // 使用this通过自定义组件内部方法调用,无法触发UI刷新
          //  this.changeScore2(this.score);  -- 不推荐

          // 通过赋值添加 Proxy 代理 -- 推荐
          let score2 = this.score;
          this.changeScore2(score2);
        })
    }
  }
}

谢谢大家!!!

文档中心

HarmonyOS鸿蒙-ArkUI状态管理--多种装饰器-CSDN博客

HarmonyOS鸿蒙- 一行代码自动换行技巧_鸿蒙换行-CSDN博客

HarmonyOS鸿蒙 - 判断手机号、身份证(正则表达式)_鸿蒙 正则表达式-CSDN博客

HarmonyOS鸿蒙- 延时执行_鸿蒙 延迟执行-CSDN博客

HarmonyOS鸿蒙- 跳转系统应用能力_鸿蒙系统应用跳转设置-CSDN博客

HarmonyOS鸿蒙-DevEco Studio工具_select a device first.-CSDN博客

相关推荐
zhujian826375 小时前
三十、【鸿蒙 NEXT】实现吸顶效果
harmonyos·鸿蒙·next·吸顶·吸顶效果·nestedscroll
无穷小亮5 小时前
Flutter框架跨平台鸿蒙开发——育儿知识APP的开发流程
flutter·华为·harmonyos·鸿蒙
晚霞的不甘9 小时前
Flutter for OpenHarmony:从零到一:构建购物APP的骨架与精美UI
前端·javascript·flutter·ui·前端框架·鸿蒙
zilikew10 小时前
Flutter框架跨平台鸿蒙开发——高尔夫计分器APP的开发流程
flutter·华为·harmonyos·鸿蒙
血色橄榄枝11 小时前
07 复盘一阶段掌握知识要点
flutter·开源·鸿蒙
zilikew11 小时前
Flutter框架跨平台鸿蒙开发——丢件上报APP的开发流程
flutter·华为·harmonyos·鸿蒙
zilikew14 小时前
Flutter框架跨平台鸿蒙开发——谁是卧底游戏APP的开发流程
flutter·游戏·华为·harmonyos·鸿蒙
zilikew21 小时前
Flutter框架跨平台鸿蒙开发——书籍推荐APP的开发流程
flutter·华为·harmonyos·鸿蒙
zilikew21 小时前
Flutter框架跨平台鸿蒙开发——桌面宠物APP的开发流程
学习·flutter·harmonyos·鸿蒙·宠物
zilikew1 天前
Flutter框架跨平台鸿蒙开发——小语种学习APP的开发流程
学习·flutter·华为·harmonyos·鸿蒙