前言:

1、我们一起来学习鸿蒙V2装饰器的使用。我们从官方文档和示例代码入手,学习并实践,看完这篇博客,你会有所收获。

2、本博客尽量以简单的方式呈现核心的用法,提供完整的运行效果和示例代码。

一、下方是官方文档和示例仓库的链接:

文档中心https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-mvvm-v2GitCode - 全球开发者的开源社区,开源代码托管平台GitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/ArkUISample/StateMgmtV2MVVM二、下面是V2装饰器的用法,口语化版,不包准确:

1、@ComponentV2 修饰自定义组件(个人理解,和@Component的用法差不多,功能也相似,但是能在这个组件内使用别的V2装饰器,你就需要使用@ComponentV2修饰组件

2、@Local 用法和@State差不多,用来修饰状态变量的。

LocalView.ets

@Entry
@ComponentV2
export struct LocalView {
  @Local isFinish: number = 0;

  build() {
    Column() {
      Text(this.isFinish.toString())
        .fontSize(40)
        .margin({ bottom: 10 })
        .onClick(() => this.isFinish++)
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }
}

3、@Param 用在V2子组件,用来修饰变量,接收V2父组件传递的数据

4、@Once 配合@Param使用,使子组件的参数变量变成状态变量,改变了值UI也会更新。

ParamView.ets

@ComponentV2
struct ParamViewItem {
  @Param taskName: string = '';
  @Param @Once isFinish: boolean = false;

  build() {
    Row() {
      Text(this.taskName)
        .fontSize(20)
        .decoration({ type: this.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
    }
    .onClick(() => this.isFinish = !this.isFinish)
  }
}

@Entry
@ComponentV2
export struct ParamView {
  build() {
    Column() {
      Text("ParamView的父组件标题")
        .fontSize(40)
        .margin({ bottom: 10 })
      ParamViewItem({ taskName: '子组件 1', isFinish: false })
      ParamViewItem({ taskName: '子组件 2', isFinish: false })
      ParamViewItem({ taskName: '子组件 3', isFinish: false })
    }
  }
}

5、@Event 修饰V2子组件的方法,使得V2父组件可以传递方法进去

EventView.ets

@ComponentV2
struct TaskItem {
  @Param taskName: string = '';
  @Param @Once isFinish: boolean = false;
  @Event deleteTask: () => void = () => {
  };

  build() {
    Row() {

      Text(this.taskName)
        .decoration({ type: this.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
      Button("删除")
        .onClick(() => this.deleteTask())
    }
    .onClick(() => this.isFinish = !this.isFinish)
  }
}

@Entry
@ComponentV2
export struct EventView {
  @Local tasks: string[] = ['task1', 'task2', 'task3'];
  @Local newTaskName: string = '';

  build() {
    Column() {
      Text("父组件")
        .fontSize(40)
        .margin({ bottom: 10 })
      ForEach(this.tasks, (task: string) => {
        TaskItem({
          taskName: task,
          isFinish: false,
          deleteTask: () => this.tasks.splice(this.tasks.indexOf(task), 1)
        })
      })
      Row() {
        TextInput({ placeholder: "输入文字", text: this.newTaskName })
          .onChange((value) => this.newTaskName = value)
          .width('70%')
        Button('+')
          .onClick(() => {
            this.tasks.push(this.newTaskName);
            this.newTaskName = '';
          })
      }
    }
  }
}

6、@ObservedV2  @Trace 这两个装饰器配合使用,检测类参数变化

ObservedV2.ets

@ObservedV2
class Task {
  public taskName: string = '';
  @Trace public isFinish: boolean = false;

  constructor(taskName: string, isFinish: boolean) {
    this.taskName = taskName;
    this.isFinish = isFinish;
  }
}

@ComponentV2
struct TaskItem {
  @Param task: Task = new Task('', false);
  @Event deleteTask: () => void = () => {
  };

  build() {
    Row() {
      Image(this.task.isFinish ? $r('app.media.startIcon') : $r('app.media.background'))
        .width(28)
        .height(28)
      Text(this.task.taskName)
        .decoration({ type: this.task.isFinish ? TextDecorationType.LineThrough : TextDecorationType.None })
      Button("删除")
        .onClick(() => this.deleteTask())
    }
    .onClick(() => this.task.isFinish = !this.task.isFinish)
  }
}

@Entry
@ComponentV2
export struct ObservedV2View {
  @Local tasks: Task[] = [
    new Task('task1', false),
    new Task('task2', false),
    new Task('task3', false),
  ];
  @Local newTaskName: string = '';

  finishAll(ifFinish: boolean) {
    for (let task of this.tasks) {
      task.isFinish = ifFinish;
    }
  }

  build() {
    Column() {
      Text("父组件标题")
        .fontSize(40)
        .margin({ bottom: 10 })
      Repeat<Task>(this.tasks)
        .each((obj: RepeatItem<Task>) => {
          TaskItem({
            task: obj.item,
            deleteTask: () => this.tasks.splice(this.tasks.indexOf(obj.item), 1)
          })
        })
      Row() {
        Button("完成所有的任务")
          .onClick(() => this.finishAll(true))
        Button("取消")
          .onClick(() => this.finishAll(false))
      }

      Row() {
        TextInput({ placeholder: "添加新的任务", text: this.newTaskName })
          .onChange((value) => this.newTaskName = value)
          .width('70%')
        Button('+')
          .onClick(() => {
            this.tasks.push(new Task(this.newTaskName, false));
            this.newTaskName = '';
          })
      }
    }
  }
}

以上是个人经验分享

Logo

更多推荐