HarmonyOS 应用开发 —— 常用装饰器整理

2023-12-18 12:09:13 浏览数 (2)

HarmonyOS 应用开发 —— 常用装饰器整理

当前版本:API9 纯 ArcTS 语言和 Stage模式

学习 HarmonyOS 时,我们会用到各种各样的装饰器。

我们使用 DevEco IDLE 进行 HarmonyOS 应用开发时,在任意 .ets 文件中,输入 @ 时,会弹出所有的装饰器,但是什么时候该用什么装饰器就需要查文档。但是官方文档没有搜到和装饰器强相关的文档。

故自行总结常用装饰器的学习笔记

PS:由于楼主也在学习的过程中,所以可能有些地方写的不是很清晰,欢迎大家来指正

一、修饰 struct 或 class

@Entry

作用:表示自定义组件入口,一个组件有且只能拥有一个入口,及入口组件

案例:我们默认创建的项目,默认生成的文件就包含了 @Entry

代码语言:javascript复制
@Entry
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
    Row() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
    }
    .height('100%')
  }
}
@Conponent

作用:表示当前 struct 是一个组件,可以单独使用,封装抽离文件

案例:使用方式如下,如果需要让别的组件使用该自定义组件,使用 import/export 语法 导出以及导入即可

代码语言:javascript复制
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
      Column() {
        Text(this.message)
          .fontSize(50)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
  }
}
@Preview

作用:Dev Eco 预览器提供的一个快捷注解,可以快速预览单个页面,以及组件

使用:

代码语言:javascript复制
@Preview
@Entry      // 使用了 @Preview 组件,@Entry 注解就不再是必要的了
@Component
struct TaskPage {
    // ....
}
@Observed

作用:新闻发布案例中 NewsViewModel 会用到,会与变量修饰器 @ObjectLink 一起使用,可以挂多个组件建立连接

使用:

代码语言:javascript复制
@Observed
export class CustomRefreshLoadLayoutClass {
  /**
   * Custom refresh load layout isVisible.
   */
  isVisible: boolean;

  /**
   * Custom refresh load layout imageSrc.
   */
  imageSrc: Resource;

  /**
   * Custom refresh load layout textValue.
   */
  textValue: Resource;

  /**
   * Custom refresh load layout heightValue.
   */
  heightValue: number;

  constructor(isVisible: boolean, imageSrc: Resource, textValue: Resource, heightValue: number) {
    this.isVisible = isVisible;
    this.imageSrc = imageSrc;
    this.textValue = textValue;
    this.heightValue = heightValue;
  }
}

二、修饰变量

@State

作用:用于组件内状态管理,使用该装饰器修饰的变量,当变量值发生改变后,会触发 ArkUI 的更新

案例:

代码语言:javascript复制
@Component
struct Index {
  @State message: string = 'Hello World'

  build() {
      Column() {
        Text(this.message)  // 在 HarmonOS 中并没有抛弃 this 的概念!
        // ..
      }
    // ..
  }
}
@Prop

作用:父组件 -> 子组件,单向同步状态

TODO:实际开发中暂时未遇到,如遇到了,在更新

@Link

父子组件双向同步状态

使用:

父组件

代码语言:javascript复制
// ...

@Preview
@Component
export default struct TabBar {
  @State tabBarArray: NewsTypeBean[] = NewsViewModel.getDefaultTypeList();
  @State currentIndex: number = 0;     // 定义 State 状态变量
  @State currentPage: number = 1;

  // ....

  build() {
    Tabs() {
      ForEach(this.tabBarArray, (tabItems: NewsTypeBean) => {
        TabContent() {
          Column() {
            NewsList({ currentIndex: $currentIndex })   // 这里传递的是引用
          }
        }
        .tabBar(this.TabBuilder(tabItems.id))
      }, (item: NewsTypeBean) => JSON.stringify(item))
    }
    // ...
    .vertical(false)
  }
}

子组件

代码语言:javascript复制
export default struct NewsList {
  @State newsModel: NewsModel = new NewsModel();
  @Watch('changeCategory') @Link currentIndex: number;

  // 定义监听函数
  changeCategory() {
    this.newsModel.currentPage = 1;
    NewsViewModel.getNewsList(this.newsModel.currentPage, this.newsModel.pageSize, Const.GET_NEWS_LIST)
      .then((data: NewsData[]) => {
        this.newsModel.pageState = PageState.Success;
        if (data.length === this.newsModel.pageSize) {
          this.newsModel.currentPage  ;
          this.newsModel.hasMore = true;
        } else {
          this.newsModel.hasMore = false;
        }
        this.newsModel.newsData = data;
      })
      .catch((err: string | Resource) => {
        promptAction.showToast({
          message: err,
          duration: Const.ANIMATION_DURATION
        });
        this.newsModel.pageState = PageState.Fail;
      });
  }
  
  aboutToAppear() {
    // Request news data
    this.changeCategory();
  }

    // ..
}
@Watch

和 @Link 一起使用,监听状态变化

使用:见上一个案例

@Provide [待更新]

作用:跨组件通信,可以给祖父组件的变量修饰

@Consume [待更新]

作用:跨组件通信,可以给孙子组件的变量修饰

@ObjectLink [待更新]

与被 @Observed 修饰过的 class 结合一起使用,具体作用待了解

TODO: 暂时还未摸清楚具体作用,也没有合适的案例,暂时先不提供了

三、修饰函数

使用修饰函数的装饰器,我们可以进一步抽离繁杂冗余的样式,可复用的代码逻辑,降低代码的复杂程度

@Builder

作用:用来修饰一个函数,快速生成布局内容,从而避免编写重复的样式,可以直接封装一个可复用 并且附带样式 的组件

案例:

代码语言:javascript复制
@Component
export default struct TodoItem {

  @State isComplete: boolean = false;
  @Builder labelIcon(url) {
    Image(url)
      .objectFit(ImageFit.Contain)
      .width(24)
      .height(24)
      .margin({
        right: 15,
        top: 5
      })
  }


build() {
    Row() {
        if (this.isComplete) {
            this.labelIcon($r("app.media.select"))
        } else {
            this.labelIcon($r("app.media.unselect"))
        }

        // ..
        }
    }
}

@Style

作用:用来修饰一个函数,保存样式,可以直接提供给组件使用

语法:

代码语言:javascript复制
// 统一卡片样式
@Styles function card() {
  .width('95%')
  .padding(20)
  .backgroundColor(0xffffff)
  .borderRadius(15)
  .shadow({ radius: 6, color: 0x1F000000, offsetX: 2, offsetY: 4})
}

@Extend

作用:继承一个内置组件,并且开发者可扩展出其他常用属性

语法:

代码语言:javascript复制
@Extend(Text) function finishedTask() {
  .decoration({ type: TextDecorationType.LineThrough })
  .fontColor(0xB1B2B1)
}

案例:

代码语言:javascript复制
    // ...

    Row() {
        Text(item.name)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .finishedTask()
    }

    // ...

// 这里需要定在 struct 文件之外
@Extend(Text) function finishedTask() {
  .decoration({ type: TextDecorationType.LineThrough })
  .fontColor(0xB1B2B1)
}

0 人点赞