在 HarmonyOS 應用開發工作中,我頻繁碰到組件初始化傳參校驗的難題。在復雜的組件嵌套里,要是無法確保必要參數在構造時準確傳入,就極易引發運行時錯誤,而且排查起來費時費力。一次偶然的機會,我接觸到了?@Require
?裝飾器,它能在編譯階段就對組件構造傳參進行嚴格校驗,大大提升了代碼的健壯性和開發效率。然而在學習過程中,我發現相關資料零散且缺乏系統性。因此,我決定撰寫這篇博客,把自己的學習經驗和實踐成果分享出來,助力更多開發者快速掌握?@Require
?裝飾器的使用方法。
1. HarmonyOS 開發文檔概述
HarmonyOS 開發文檔為開發者提供了全面且細致的指導,涵蓋了從基礎入門到高級 API 應用的各個方面。當前使用的是 HarmonyOS 5.0.3 (15) 版本,其 API 能力級別為 API 15 Release。詳細的版本配套關系可參考版本說明文檔,這有助于我們精準地使用適合當前版本的 API 功能。
2. @Require 裝飾器概述
2.1 定義與作用
@Require
?是一個用于校驗?@Prop
、@State
、@Provide
、@BuilderParam
?和普通變量(無狀態裝飾器修飾的變量)是否需要構造傳參的裝飾器。當它與這些變量結合使用時,在構造自定義組件時,這些變量必須在構造時傳參,否則編譯將無法通過。
2.2 版本支持情況
- 從 API version 11 開始,
@Require
?對?@Prop
?和?@BuilderParam
?進行校驗,并且支持在元服務中使用。 - 從 API version 12 開始,它對?
@State
、@Provide
?和普通變量(無狀態裝飾器修飾的變量)進行校驗。
3. @Require 裝飾器的限制條件
3.1 修飾范圍限制
@Require
?裝飾器僅能用于裝飾?struct
?內的?@Prop
、@State
、@Provide
、@BuilderParam
?和普通變量(無狀態裝飾器修飾的變量)。如果在其他地方使用,會導致代碼不符合規范。
3.2 預覽器限制
預覽器限制場景需要參考?PreviewChecker
?檢測規則。這意味著在使用預覽器查看組件效果時,需要確保代碼符合相關規則,否則可能無法正常預覽。
4. @Require 裝飾器的使用場景
4.1 父子組件傳參校驗
當?Child
?組件內使用?@Require
?裝飾器和?@Prop
、@State
、@Provide
、@BuilderParam
?和普通變量(無狀態裝飾器修飾的變量)結合使用時,父組件?Index
?在構造?Child
?時必須傳參,否則編譯不通過。以下是一個示例代碼:
@Entry
@Component
struct Index {@State message: string = 'Hi, HarmonyOS';@Builder buildTest() {Row() {Text('Hi, Harmony World').fontSize(40)}}build() {Row() {Child({ regular_value: this.message, state_value: this.message, provide_value: this.message, initMessage: this.message, message: this.message,buildTest: this.buildTest, initBuildTest: this.buildTest })}}
}@Component
struct Child {@Builder buildFunction() {Column() {Text('initBuilderParam - Custom').fontSize(40).fontColor('#FF8C00')}}@Require regular_value: string = 'Hi';@Require @State state_value: string = "Hi";@Require @Provide provide_value: string = "Hi";@Require @BuilderParam buildTest: () => void;@Require @BuilderParam initBuildTest: () => void = this.buildFunction;@Require @Prop initMessage: string = 'Hi';@Require @Prop message: string;build() {Column() {Text(this.initMessage).fontSize(40).fontColor('#008080')Text(this.message).fontSize(40).fontColor('#008080')this.initBuildTest();this.buildTest();}.width('100%').height('100%')}
}
在這個示例中,父組件?Index
?在構造?Child
?組件時,為?Child
?組件的所有使用?@Require
?裝飾的變量都傳遞了參數,確保了編譯的順利通過。同時,對文本的字體大小和顏色進行了修改,增強了視覺效果。
4.2 使用 @ComponentV2 修飾的組件初始化
使用?@ComponentV2
?修飾的自定義組件?ChildPage
?通過父組件?ParentPage
?進行初始化,因為有?@Require
?裝飾,所以父組件必須進行構造賦值。以下是示例代碼:
@ObservedV2
class Info {@Trace name: string = '';@Trace age: number = 0;
}@ComponentV2
struct ChildPage {@Require @Param childInfo: Info = new Info();@Require @Param state_value: string = "Hi";build() {Column() {Text(`ChildPage childInfo name :${this.childInfo.name}`).fontSize(30).fontWeight(FontWeight.Bold).fontColor('#FF69B4')Text(`ChildPage childInfo age :${this.childInfo.age}`).fontSize(30).fontWeight(FontWeight.Bold).fontColor('#FF69B4')Text(`ChildPage state_value :${this.state_value}`).fontSize(30).fontWeight(FontWeight.Bold).fontColor('#FF69B4')}}
}@Entry
@ComponentV2
struct ParentPage {info1: Info = { name: "Charlie", age: 35 };label1: string = "HarmonyOS Is Great";@Local info2: Info = { name: "Charlie", age: 35 };@Local label2: string = "HarmonyOS Is Great";build() {Column() {Text(`info1: ${this.info1.name} ${this.info1.age}`) .fontSize(40).fontWeight(FontWeight.Bold).fontColor('#8A2BE2')ChildPage({ childInfo: this.info1, state_value: this.label1}) Line().width('100%').height(8).backgroundColor('#FF0000').margin(15)Text(`info2: ${this.info2.name} ${this.info2.age}`) .fontSize(40).fontWeight(FontWeight.Bold).fontColor('#8A2BE2')ChildPage({ childInfo: this.info2, state_value: this.label2}) Line().width('100%').height(8).backgroundColor('#FF0000').margin(15)Button("Update info1&info2").onClick(() => {this.info1 = { name: "David", age: 28} this.info2 = { name: "David", age: 28} this.label1 = "New Fantastic Message"; this.label2 = "New Fantastic Message"; })}}
}
在這個示例中,父組件?ParentPage
?在初始化?ChildPage
?組件時,為?ChildPage
?組件的?childInfo
?和?state_value
?傳遞了參數,保證了組件的正常初始化。同時,對文本的字體大小、顏色以及線條的高度、顏色和邊距進行了修改,使界面更加美觀。
5. 錯誤場景分析
如果在使用?@Require
?裝飾器時沒有在構造時傳參,會導致編譯錯誤。以下是一個錯誤示例:
@Entry
@Component
struct Index {@State message: string = 'Hello World';@Builder buildTest() {Row() {Text('Hello, world').fontSize(32)}}build() {Row() {Child()}}
}@Component
struct Child {@Builder buildFunction() {Column() {Text('initBuilderParam - Error Case').fontSize(32).fontColor('#FF00FF')}}// 使用@Require必須構造時傳參。@Require regular_value: string = 'Hello';@Require @State state_value: string = "Hello";@Require @Provide provide_value: string = "Hello";@Require @BuilderParam initBuildTest: () => void = this.buildFunction;@Require @Prop initMessage: string = 'Hello';build() {Column() {Text(this.initMessage).fontSize(32).fontColor('#FF00FF')this.initBuildTest();}}
}
在這個示例中,父組件?Index
?在構造?Child
?組件時沒有傳遞任何參數,由于?Child
?組件中的變量使用了?@Require
?裝飾器,所以這段代碼在編譯時會報錯。同時,對文本的字體大小和顏色進行了修改,方便區分不同的代碼部分。
6. 總結
@Require
?裝飾器在 HarmonyOS 開發中是一個非常實用的工具,它可以幫助我們在編譯階段就發現組件構造傳參的問題,避免運行時錯誤,提高代碼的穩定性和可維護性。通過本文的介紹,你應該對?@Require
?裝飾器的使用有了更深入的理解。在實際開發中,合理運用?@Require
?裝飾器,能夠讓你的代碼更加健壯,開發過程更加順暢。
最后希望這篇自學指南能對你有所幫助,讓你在 HarmonyOS 開發的道路上更進一步,當然對鴻蒙有興趣的同學也歡迎點贊、收藏~!