@Provide裝飾器和@Consume裝飾器:與后代組件雙向同步

2024-01-25 12:04 更新

@Provide和@Consume,應(yīng)用于與后代組件的雙向數(shù)據(jù)同步,應(yīng)用于狀態(tài)數(shù)據(jù)在多個(gè)層級(jí)之間傳遞的場(chǎng)景。不同于上文提到的父子組件之間通過(guò)命名參數(shù)機(jī)制傳遞,@Provide和@Consume擺脫參數(shù)傳遞機(jī)制的束縛,實(shí)現(xiàn)跨層級(jí)傳遞。

其中@Provide裝飾的變量是在祖先節(jié)點(diǎn)中,可以理解為被“提供”給后代的狀態(tài)變量。@Consume裝飾的變量是在后代組件中,去“消費(fèi)(綁定)”祖先節(jié)點(diǎn)提供的變量。

說(shuō)明

從API version 9開始,這兩個(gè)裝飾器支持在ArkTS卡片中使用。

概述

@Provide/@Consume裝飾的狀態(tài)變量有以下特性:

  • @Provide裝飾的狀態(tài)變量自動(dòng)對(duì)其所有后代組件可用,即該變量被“provide”給他的后代組件。由此可見,@Provide的方便之處在于,開發(fā)者不需要多次在組件之間傳遞變量。
  • 后代通過(guò)使用@Consume去獲取@Provide提供的變量,建立在@Provide和@Consume之間的雙向數(shù)據(jù)同步,與@State/@Link不同的是,前者可以在多層級(jí)的父子組件之間傳遞。
  • @Provide和@Consume可以通過(guò)相同的變量名或者相同的變量別名綁定,變量類型必須相同。
  1. // 通過(guò)相同的變量名綁定
  2. @Provide a: number = 0;
  3. @Consume a: number;
  4. // 通過(guò)相同的變量別名綁定
  5. @Provide('a') b: number = 0;
  6. @Consume('a') c: number;

@Provide和@Consume通過(guò)相同的變量名或者相同的變量別名綁定時(shí),@Provide修飾的變量和@Consume修飾的變量是一對(duì)多的關(guān)系。不允許在同一個(gè)自定義組件內(nèi),包括其子組件中聲明多個(gè)同名或者同別名的@Provide裝飾的變量。

裝飾器說(shuō)明

@State的規(guī)則同樣適用于@Provide,差異為@Provide還作為多層后代的同步源。

@Provide變量裝飾器

說(shuō)明

裝飾器參數(shù)

別名:常量字符串,可選。

如果指定了別名,則通過(guò)別名來(lái)綁定變量;如果未指定別名,則通過(guò)變量名綁定變量。

同步類型

雙向同步。

從@Provide變量到所有@Consume變量以及相反的方向的數(shù)據(jù)同步。雙向同步的操作與@State和@Link的組合相同。

允許裝飾的變量類型

Object、class、string、number、boolean、enum類型,以及這些類型的數(shù)組。嵌套類型的場(chǎng)景請(qǐng)參考觀察變化。

不支持any,不支持簡(jiǎn)單類型和復(fù)雜類型的聯(lián)合類型,不允許使用undefined和null。

必須指定類型。@Provide變量的@Consume變量的類型必須相同。

說(shuō)明

不支持Length、ResourceStr、ResourceColor類型,Length、ResourceStr、ResourceColor為簡(jiǎn)單類型和復(fù)雜類型的聯(lián)合類型。

被裝飾變量的初始值

必須指定。

@Consume變量裝飾器

說(shuō)明

裝飾器參數(shù)

別名:常量字符串,可選。

如果提供了別名,則必須有@Provide的變量和其有相同的別名才可以匹配成功;否則,則需要變量名相同才能匹配成功。

同步類型

雙向:從@Provide變量(具體請(qǐng)參見@Provide)到所有@Consume變量,以及相反的方向。雙向同步操作與@State和@Link的組合相同。

允許裝飾的變量類型

Object、class、string、number、boolean、enum類型,以及這些類型的數(shù)組。嵌套類型的場(chǎng)景請(qǐng)參考觀察變化。

不支持any,不允許使用undefined和null。

必須指定類型。@Provide變量的@Consume變量的類型必須相同。

說(shuō)明
  • @Consume裝飾的變量,在其父節(jié)點(diǎn)或者祖先節(jié)點(diǎn)上,必須有對(duì)應(yīng)的屬性和別名的@Provide裝飾的變量。

被裝飾變量的初始值

無(wú),禁止本地初始化。

變量的傳遞/訪問(wèn)規(guī)則說(shuō)明

@Provide傳遞/訪問(wèn)

說(shuō)明

從父組件初始化和更新

可選,允許父組件中常規(guī)變量、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp裝飾的變量裝飾變量初始化子組件@Provide。

用于初始化子組件

允許,可用于初始化@State、@Link、@Prop、@Provide。

和父組件同步

否。

和后代組件同步

和@Consume雙向同步。

是否支持組件外訪問(wèn)

私有,僅可以在所屬組件內(nèi)訪問(wèn)。

圖1 @Provide初始化規(guī)則圖示

@Consume傳遞/訪問(wèn)

說(shuō)明

從父組件初始化和更新

禁止。通過(guò)相同的變量名和alias(別名)從@Provide初始化。

用于初始化子組件

允許,可用于初始化@State、@Link、@Prop、@Provide。

和祖先組件同步

和@Provide雙向同步。

是否支持組件外訪問(wèn)

私有,僅可以在所屬組件內(nèi)訪問(wèn)

圖2 @Consume初始化規(guī)則圖示

觀察變化和行為表現(xiàn)

觀察變化

  • 當(dāng)裝飾的數(shù)據(jù)類型為boolean、string、number類型時(shí),可以觀察到數(shù)值的變化。
  • 當(dāng)裝飾的數(shù)據(jù)類型為class或者Object的時(shí)候,可以觀察到賦值和屬性賦值的變化(屬性為Object.keys(observedObject)返回的所有屬性)。
  • 當(dāng)裝飾的對(duì)象是array的時(shí)候,可以觀察到數(shù)組的添加、刪除、更新數(shù)組單元。

框架行為

  1. 初始渲染:
    1. @Provide裝飾的變量會(huì)以map的形式,傳遞給當(dāng)前@Provide所屬組件的所有子組件;
    2. 子組件中如果使用@Consume變量,則會(huì)在map中查找是否有該變量名/alias(別名)對(duì)應(yīng)的@Provide的變量,如果查找不到,框架會(huì)拋出JS ERROR;
    3. 在初始化@Consume變量時(shí),和@State/@Link的流程類似,@Consume變量會(huì)保存在map中查找到的@Provide變量,并把自己注冊(cè)給@Provide。
  2. 當(dāng)@Provide裝飾的數(shù)據(jù)變化時(shí):
    1. 通過(guò)初始渲染的步驟可知,子組件@Consume已把自己注冊(cè)給父組件。父組件@Provide變量變更后,會(huì)遍歷更新所有依賴它的系統(tǒng)組件(elementid)和狀態(tài)變量(@Consume);
    2. 通知@Consume更新后,子組件所有依賴@Consume的系統(tǒng)組件(elementId)都會(huì)被通知更新。以此實(shí)現(xiàn)@Provide對(duì)@Consume狀態(tài)數(shù)據(jù)同步。
  3. 當(dāng)@Consume裝飾的數(shù)據(jù)變化時(shí):
    1. 通過(guò)初始渲染的步驟可知,子組件@Consume持有@Provide的實(shí)例。在@Consume更新后調(diào)用@Provide的更新方法,將更新的數(shù)值同步回@Provide,以此實(shí)現(xiàn)@Consume向@Provide的同步更新。

使用場(chǎng)景

在下面的示例是與后代組件雙向同步狀態(tài)@Provide和@Consume場(chǎng)景。當(dāng)分別點(diǎn)擊CompA和CompD組件內(nèi)Button時(shí),reviewVotes 的更改會(huì)雙向同步在CompA和CompD中。

  1. @Component
  2. struct CompD {
  3. // @Consume裝飾的變量通過(guò)相同的屬性名綁定其祖先組件CompA內(nèi)的@Provide裝飾的變量
  4. @Consume reviewVotes: number;
  5. build() {
  6. Column() {
  7. Text(`reviewVotes(${this.reviewVotes})`)
  8. Button(`reviewVotes(${this.reviewVotes}), give +1`)
  9. .onClick(() => this.reviewVotes += 1)
  10. }
  11. .width('50%')
  12. }
  13. }
  14. @Component
  15. struct CompC {
  16. build() {
  17. Row({ space: 5 }) {
  18. CompD()
  19. CompD()
  20. }
  21. }
  22. }
  23. @Component
  24. struct CompB {
  25. build() {
  26. CompC()
  27. }
  28. }
  29. @Entry
  30. @Component
  31. struct CompA {
  32. // @Provide裝飾的變量reviewVotes由入口組件CompA提供其后代組件
  33. @Provide reviewVotes: number = 0;
  34. build() {
  35. Column() {
  36. Button(`reviewVotes(${this.reviewVotes}), give +1`)
  37. .onClick(() => this.reviewVotes += 1)
  38. CompB()
  39. }
  40. }
  41. }
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)