# @Require装饰器：校验构造传参

@Require是校验@Prop、@State、@Provide、@BuilderParam、@Param和普通变量（无状态装饰器修饰的变量）是否需要构造传参的一个装饰器。

从API version 11开始对@Prop/@BuilderParam进行校验。

从API version 11开始，该装饰器支持在ArkTS卡片中使用。

从API version 11开始，该装饰器支持在元服务中使用。

从API version 12开始对@State/@Provide/@Param/普通变量（无状态装饰器修饰的变量）进行校验。

#### 概述

当@Require装饰器和@Prop、@State、@Provide、@Param、@BuilderParam、普通变量（无状态装饰器修饰的变量）结合使用时，在构造该自定义组件时，@Prop、@State、@Provide、@Param、@BuilderParam和普通变量（无状态装饰器修饰的变量）必须在构造时传参。

#### 限制条件

@Require装饰器仅用于装饰struct内的@Prop、@State、@Provide、@BuilderParam、@Param和普通变量（无状态装饰器修饰的变量）。

预览器的限制场景请参考PreviewChecker检测规则。

#### 使用场景

当Child组件内使用@Require装饰器和@Prop、@State、@Provide、@BuilderParam、@Param和普通变量（无状态装饰器修饰的变量）结合使用时，父组件SceneRequire在构造Child时必须传参，否则编译不通过。

```
@Entry
@Component
struct SceneRequire {
  @State message: string = 'Hello World';

  @Builder
  buildTest() {
    Row() {
      Text('Hello, world')
        .fontSize(30)
    }
  }

  build() {
    Row() {
      // 构造Child时需传入所有@Require对应参数，否则编译失败。
      Child({
        regularValue: this.message,
        stateValue: this.message,
        provideValue: this.message,
        initMessage: this.message,
        message: this.message,
        buildTest: this.buildTest,
        initBuildTest: this.buildTest
      })
    }
  }
}

@Component
struct Child {
  @Require regularValue: string;
  @Require @State stateValue: string;
  @Require @Provide provideValue: string;
  @Require @BuilderParam buildTest: () => void;
  @Require @BuilderParam initBuildTest: () => void;
  @Require @Prop initMessage: string;
  @Require @Prop message: string;

  build() {
    Column() {
      Text(this.initMessage)
        .fontSize(30)
      Text(this.message)
        .fontSize(30)
      this.initBuildTest();
      this.buildTest();
    }
    .width('100%')
    .height('100%')
  }
}
```

使用@ComponentV2修饰的自定义组件ChildPage通过父组件ParentPage进行初始化，因为有@Require装饰@Param，所以父组件必须进行构造赋值。

```
@ObservedV2
class Info {
  @Trace public name: string = '';
  @Trace public age: number = 0;
}

@ComponentV2
struct ChildPage {
  @Require @Param childInfo: Info;
  @Require @Param stateValue: string;

  build() {
    Column() {
      Text(`ChildPage childInfo name :${this.childInfo.name}`)
        .fontSize(15)
        .height(30)
      Text(`ChildPage childInfo age :${this.childInfo.age}`)
        .fontSize(15)
        .height(30)
      Text(`ChildPage stateValue :${this.stateValue}`)
        .fontSize(15)
        .height(30)
    }
  }
}

@Entry
@ComponentV2
struct ParentPage {
  info1: Info = { name: 'Tom', age: 25 };
  label1: string = 'Hello World';
  @Local info2: Info = { name: 'Tom', age: 25 };
  @Local label2: string = 'Hello World';

  build() {
    Column() {
      Text(`info1: ${this.info1.name}  ${this.info1.age}`) // Text1。
        .fontSize(25)
        .height(30)
      // 父组件ParentPage构造子组件ChildPage时进行了构造赋值。
      // 为ChildPage中被@Require @Param装饰的childInfo和stateValue属性传入了值。
      ChildPage({ childInfo: this.info1, stateValue: this.label1 }) // 创建自定义组件。
      Text(`info2: ${this.info2.name}  ${this.info2.age}`) // Text2。
        .fontSize(25)
        .height(30)
      // 同上，在父组件创建子组件的过程中进行构造赋值。
      ChildPage({ childInfo: this.info2, stateValue: this.label2 }) // 创建自定义组件。
      Button('change info1&info2')
        .onClick(() => {
          this.info1 = { name: 'Cat', age: 18 }; // Text1不会刷新，原因是info1没有装饰器装饰，监听不到值的改变。
          this.info2 = { name: 'Cat', age: 18 }; // Text2会刷新，原因是info2有装饰器装饰，能够监听到值的改变。
          this.label1 = 'Luck'; // 不会刷新，原因是label1没有装饰器装饰，监听不到值的改变。
          this.label2 = 'Luck'; // 会刷新，原因是label2有装饰器装饰，可以监听到值的改变。
        })
    }
    .width('100%')
  }
}
```

从API version 18开始，使用@Require装饰@State、@Prop、@Provide装饰的状态变量，可以在无本地初始值的情况下直接在组件内使用，不会编译报错。

```
@Entry
@Component
struct PageOne {
  message: string = 'Hello World';

  build() {
    Column() {
      ChildIndex({ message: this.message })
    }
  }
}

@Component
struct ChildIndex {
  @Require @State message: string;

  build() {
    Column() {
      Text(this.message) // 从API version 18开始，可以编译通过。
    }
  }
}
```

#### 常见问题

当状态管理V1组件内将@Require装饰器与@Prop、@State、@Provide、@BuilderParam、普通变量（无状态装饰器修饰的变量）结合使用时，若父组件Index在构造Child时未传递相应参数，则会导致编译失败。当状态管理V2组件内将@Require装饰器与@Param结合使用时，若父组件Index在构造ChildV2时未传递相应参数，则同样会导致编译失败。

【反例】

```
@Entry
@Component
struct Index {
  @State message: string = 'Hello World!';

  @Builder
  buildTest() {
    Row() {
      Text('Hello, world!!')
        .fontSize(30)
    }
  }

  build() {
    Row() {
      // 构造Child、ChildV2组件时没有传参，会导致编译不通过。
      Child()
      ChildV2()
    }
  }
}

@Component
struct Child {
  // 使用@Require必须构造时传参。
  @Require regularValue: string;
  @Require @State stateValue: string;
  @Require @Provide provideValue: string;
  @Require @BuilderParam initBuildTest: () => void;
  @Require @Prop initMessage: string;

  build() {
    Column() {
      Text(this.initMessage)
        .fontSize(30)
      this.initBuildTest();
    }
  }
}

@ComponentV2
struct ChildV2 {
  // 使用@Require必须构造时传参。
  @Require @Param message: string;

  build() {
    Column() {
      Text(this.message)
    }
  }
}
```

当父组件Example在构造ChildV1与ChildV2时传递了相应的参数，则编译通过。

【正例】

```
@Entry
@Component
struct Example {
  @State message: string = 'Hello World!';

  @Builder
  buildTest() {
    Row() {
      Text('Hello, world!!')
        .fontSize(30)
    }
  }

  build() {
    Row() {
      // 构造ChildV1、ChildV2组件时传递相应参数，编译通过。
      ChildV1({
        regularValue: 'Hello',
        stateValue: 'Hello',
        provideValue: 'Hello',
        initBuildTest: this.buildTest,
        initMessage: 'Hello'
      })
      ChildV2({ message: this.message })
    }
  }
}

@Component
struct ChildV1 {
  // 使用@Require必须构造时传参。
  @Require regularValue: string;
  @Require @State stateValue: string;
  @Require @Provide provideValue: string;
  @Require @BuilderParam initBuildTest: () => void;
  @Require @Prop initMessage: string;

  build() {
    Column() {
      Text(this.initMessage)
        .fontSize(30)
      this.initBuildTest();
    }
  }
}

@ComponentV2
struct ChildV2 {
  // 使用@Require必须构造时传参。
  @Require @Param message: string;

  build() {
    Column() {
      Text(this.message)
    }
  }
}
```