ArkTs的@Watch状态监听 原创

黑臂麒麟
发布于 2025-3-31 23:33
浏览
0收藏

@Watch装饰器:监听并捕捉变量变化


@Watch用于监听状态变量的变化,当状态变量变化时,@Watch的回调方法将被调用。@Watch在ArkUI框架内部判断数值有无更新使用的是严格相等(===),监听并捕捉变量变化。
前端同学以Vue中的Watch监听为嵌入点更好理解。

装饰器说明

  • 装饰器参数: 自定义回调引用,用引号字符串的方法名称,这里类似Vue中的Watch对象中自定义方法;
  • 可装饰的自定义组件变量:可监听所有装饰器装饰的状态变量。不允许监听常规变量。
  • 装饰器的顺序: 把@State、@Prop、@Link等装饰器在@Watch装饰器之前。

语法说明

@Watch (changedPropertyName? : string) => void
  • 1.
  • changedPropertyName: 自定义函数成员,是watch的属性名;
  • 在多个状态变量绑定同一个@Watch的回调方法的时候,可以通过changedPropertyName进行不同的逻辑处理

变化和行为、限制条件

变化和行为 限制条件
当观察到状态变量的变化的时候,对应的@Watch的回调方法将被触发; 建议不要在@Watch的回调方法里修改当前装饰的状态变量和循环
@Watch方法在自定义组件的属性变更之后同步执行 应关注性能,属性值更新函数会延迟组件的重新渲染,因此,回调函数应仅执行快速运算
在第一次初始化的时候,@Watch装饰的方法不会被调用,只有在后续状态改变时才会调用 不建议在@Watch函数中调用async await 等异步,影响性能

@Watch 深度探索:与@Link、 @Povide配合使用


@Watch在项目开发中使用频率非常高,只要是想对一个变量变化监听,然后紧接着要处理其他业务就需要用到它。下面以示例codeLabs到'工作目标'案例为例:

@Link 和 @Watch配合使用

ArkTs的@Watch状态监听-鸿蒙开发者社区

// TargetList.ets
@Component
export default struct TargetList {
  ...
  @State clickIndex: number = -1;
  ...
  onAddClick?: () => void;

  build() {
    Column() {
      ...
      List({ space: CommonConstants.LIST_SPACE }) {
        ForEach(this.targetData, (item: TaskItemBean, index: number | undefined) => {
          ListItem() {
            TargetListItem({
              taskItem: item,
              index: index,
              selectArr: $selectArray,
              isEditMode: this.isEditMode,
              clickIndex: $clickIndex
            })
          }
        }, (item: TaskItemBean) => JSON.stringify(item))
      }
      ...
    }
    ...
  }
}

// TargetListItem.ets
@Component
export default struct TargetListItem {
  ...
  @Link @Watch('onClickIndexChanged') clickIndex: number;
  @State isExpanded: boolean = false;
  @Consume overAllProgressChanged: boolean;
  @State sliderMode: number = CommonConstants.DEFAULT_SLIDER_MODE;
  public index: number = 0;

  ...
  /**
   * Listening click index.
   */
  onClickIndexChanged() {
    if (this.clickIndex !== this.index) {
      this.isExpanded = false;
    }
  }

  build() {
    Stack({ alignContent: Alignment.Start }) {
      Column() {
        this.TargetItem()
        ...
        }
      }
      ...
      .onClick(() => {
        ...
        if (!this.isEditMode) {
          ...
          this.clickIndex = this.index;
        }
      })
      ...
    }
    .width(CommonConstants.FULL_WIDTH)
  }

  ...
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 本codelab中,使用@Link装饰器从父组件TargetList.ets中接收到(@Link是跨代组件同行,可以去HarmonyOS基础(四)- HarmonyOS ArkTs 组件状态查看详细说明)的双向同步的变量clickIndex,并使用@Watch监听当前变量。
  • onClickIndexChanged是我们自定义函数。当监听当点击子目标时,就改变isExpanded 的状态,这样起到展开/收起目标子组件动态变化
  • 然后子组件就根据当前clickIndex和列表下标比对,如何是与当前下标相同,不做处理,如果不是就咱开。

@Provide和@Watch 配合使用

[video(video-j1ych5oc-1707379671885)(type-csdn)(url-https://live.csdn.net/v/embed/363377)(image-https://video-community.csdnimg.cn/vod-84deb4/c081b734c65771eebfc75107e0c90102/snapshots/30ac3b013e614616acee7f99e6fb8966-00001.jpg?auth_key=4860978840-0-0-cd408bf2baf8502e95ab217e3631d573)(title-)]

@Entry
@Component
struct MainPage {
  @State targetData: Array<TaskItemBean> = DataModel.getData();
  @State totalTasksNumber: number = 0;
  @State completedTasksNumber: number = 0;
  @State latestUpdateDate: string = CommonConstants.DEFAULT_PROGRESS_VALUE;
  @Provide @Watch('onProgressChanged') overAllProgressChanged: boolean = false;
  dialogController: CustomDialogController = new CustomDialogController({
    ...
  });

  /**
   * Listening targetData.
   */
  onProgressChanged() {
    this.totalTasksNumber = this.targetData.length;
    this.completedTasksNumber = this.targetData.filter((item: TaskItemBean) => {
      return item.progressValue === CommonConstants.SLIDER_MAX_VALUE;
    }).length;
    this.latestUpdateDate = getCurrentTime();
  }
  
  build() {
    Column() {
      ...
      TargetInformation({
        latestUpdateDate: this.latestUpdateDate,
        totalTasksNumber: this.totalTasksNumber,
        completedTasksNumber: this.completedTasksNumber
      })
      ...
    }
    .width(CommonConstants.FULL_WIDTH)
    .height(CommonConstants.FULL_HEIGHT)
    .backgroundColor($r('app.color.index_background'))
  }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 本codelab中,使用@Provide装饰器定义变量(@Provide是跨代组件同步,可以在HarmonyOS基础(四)- HarmonyOS ArkTs 组件状态查看详细说明)overAllProgressChanged,并使用@Watch监听当前变量。
  • onProgressChanged是我们自定义函数,子目标进度完成并确认后。触发当前自定义函数,并赋值给变量。
  • 然后更新我们TargetInformation组件的整体进度状态。

参考:

ArkUI指南
ArkTS-API文档
HarmonyOS基础认证课程
HarmonyOS高级认证课程

​​

总结:

@Watch 装饰器和@State、@Prop、@Link是 ArkTS 框架中最基本也是最关键状态管理修饰符,通过它们的灵活运用,能够更好地处理组件之间状态的变化和同步。实际应用中,建议开发者灵活选择使用针对不同场景,并结合codeLabs和项目,以提高应用的性能和可维护性。 ArkTS 的状态管理机制为开发者提供了丰富的选择,对构建复杂应用变得更加简便与高效。

ArkTs的@Watch等状态修饰符为开发这提供组件变量管理的灵活性和控制性,对初步掌握HarmonyOS开发提供了可以精确监听状态变量的能力。在实际项目组件中极大提升代码的低耦合高内聚的能力和可维护性、高效力能力。实际开发中,也能发挥ArkTS的优势,构建强大的一次开发,多段部署的物联网应用。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
1
收藏
回复
举报
1
1
1条回复
按时间正序
/
按时间倒序
虎子船长
虎子船长

收藏一zia

回复
2025-4-3 08:39:18


回复
    相关推荐