今天是1月11日號星期四,農(nóng)歷臘月初一,辭舊的歲月里,愿你守得云開、終見月明,迎新的時(shí)光中,愿你心御寒冬、順?biāo)鞜o憂,歲末冬深,希望接下來的日子里足夠幸運(yùn),攢足勇氣、信心和運(yùn)氣,去迎接新的一年,去遇見更好的自己!
目錄
一,定義
二,特性
三,裝飾器說明
?四,變量的傳遞/訪問規(guī)則說明
五,使用
1,簡單使用
?2,裝飾對象
3,裝飾Array
一,定義
@Provide和@Consume,應(yīng)用于與后代組件的雙向數(shù)據(jù)同步,應(yīng)用于狀態(tài)數(shù)據(jù)在多個(gè)層級之間傳遞的場景。不同于其他父子組件之間通過命名參數(shù)機(jī)制傳遞,@Provide和@Consume擺脫參數(shù)傳遞機(jī)制的束縛,實(shí)現(xiàn)跨層級傳遞。
其中@Provide裝飾的變量是在祖先組件中,可以理解為被“提供”給后代的狀態(tài)變量。@Consume裝飾的變量是在后代組件中,去“消費(fèi)(綁定)”祖先組件提供的變量。
二,特性
@Provide/@Consume裝飾的狀態(tài)變量有以下特性:
①@Provide裝飾的狀態(tài)變量自動(dòng)對其所有后代組件可用,即該變量被“provide”給他的后代組件。由此可見,@Provide的方便之處在于,開發(fā)者不需要多次在組件之間傳遞變量。
②后代通過使用@Consume去獲取@Provide提供的變量,建立在@Provide和@Consume之間的雙向數(shù)據(jù)同步,與@State/@Link不同的是,前者可以在多層級的父子組件之間傳遞。
③@Provide和@Consume可以通過相同的變量名或者相同的變量別名綁定,建議類型相同,否則會發(fā)生類型隱式轉(zhuǎn)換,從而導(dǎo)致應(yīng)用行為異常。
@Provide和@Consume通過相同的變量名或者相同的變量別名綁定時(shí),@Provide修飾的變量和@Consume修飾的變量是一對多的關(guān)系。不允許在同一個(gè)自定義組件內(nèi),包括其子組件中聲明多個(gè)同名或者同別名的@Provide裝飾的變量,@Provide的屬性名或別名需要唯一且確定,如果聲明多個(gè)同名或者同別名的@Provide裝飾的變量,會發(fā)生運(yùn)行時(shí)報(bào)錯(cuò)。
三,裝飾器說明
@State的規(guī)則同樣適用于@Provide,差異為@Provide還作為多層后代的同步源。
@Provide變量裝飾器 | 說明 |
---|---|
裝飾器參數(shù) | 別名:常量字符串,可選。 如果指定了別名,則通過別名來綁定變量;如果未指定別名,則通過變量名綁定變量。 |
同步類型 | 雙向同步。 從@Provide變量到所有@Consume變量以及相反的方向的數(shù)據(jù)同步。雙向同步的操作與@State和@Link的組合相同。 |
允許裝飾的變量類型 | Object、class、string、number、boolean、enum類型,以及這些類型的數(shù)組。 支持Date類型。 不支持any,不支持簡單類型和復(fù)雜類型的聯(lián)合類型,不允許使用undefined和null。 必須指定類型。@Provide變量的@Consume變量的類型必須相同。 說明: 不支持Length、ResourceStr、ResourceColor類型,Length、ResourceStr、ResourceColor為簡單類型和復(fù)雜類型的聯(lián)合類型。 |
被裝飾變量的初始值 | 必須指定。 |
@Consume變量裝飾器 | 說明 |
---|---|
裝飾器參數(shù) | 別名:常量字符串,可選。 如果提供了別名,則必須有@Provide的變量和其有相同的別名才可以匹配成功;否則,則需要變量名相同才能匹配成功。 |
同步類型 | 雙向:從@Provide變量(具體請參見@Provide)到所有@Consume變量,以及相反的方向。雙向同步操作與@State和@Link的組合相同。 |
允許裝飾的變量類型 | Object、class、string、number、boolean、enum類型,以及這些類型的數(shù)組。 支持Date類型。 不支持any,不允許使用undefined和null。 必須指定類型。@Provide變量和@Consume變量的類型必須相同。 說明: @Consume裝飾的變量,在其父節(jié)點(diǎn)或者祖先節(jié)點(diǎn)上,必須有對應(yīng)的屬性和別名的@Provide裝飾的變量。 |
被裝飾變量的初始值 | 無,禁止本地初始化。 |
?四,變量的傳遞/訪問規(guī)則說明
@Provide傳遞/訪問 | 說明 |
---|---|
從父組件初始化和更新 | 可選,允許父組件中常規(guī)變量(常規(guī)變量對@Prop賦值,只是數(shù)值的初始化,常規(guī)變量的變化不會觸發(fā)UI刷新,只有狀態(tài)變量才能觸發(fā)UI刷新)、@State、@Link、@Prop、@Provide、@Consume、@ObjectLink、@StorageLink、@StorageProp、@LocalStorageLink和@LocalStorageProp裝飾的變量裝飾變量初始化子組件@Provide。 |
用于初始化子組件 | 允許,可用于初始化@State、@Link、@Prop、@Provide。 |
和父組件同步 | 否。 |
和后代組件同步 | 和@Consume雙向同步。 |
是否支持組件外訪問 | 私有,僅可以在所屬組件內(nèi)訪問。 |
@Consume傳遞/訪問 | 說明 |
---|---|
從父組件初始化和更新 | 禁止。通過相同的變量名和alias(別名)從@Provide初始化。 |
用于初始化子組件 | 允許,可用于初始化@State、@Link、@Prop、@Provide。 |
和祖先組件同步 | 和@Provide雙向同步。 |
是否支持組件外訪問 | 私有,僅可以在所屬組件內(nèi)訪問 |
五,使用
1,簡單使用
?子組件:
@Component
export default struct ProvideTest {
@Consume name:string
build() {
Row() {
Column() {
Text("子name:"+ this.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.name="袁震2"
})
}.width('100%')
}.height('100%')
}
}
?父組件:
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@Provide name:string ="袁震"
build() {
Column(){
Text("父name:"+this.name)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.name ="袁震1"
})
ProvideTest()
}
}
}
運(yùn)行結(jié)果:
點(diǎn)擊父name
點(diǎn)擊子name
?所以,當(dāng)裝飾的數(shù)據(jù)類型為boolean、string、number類型時(shí),可以觀察到數(shù)值的變化。
?2,裝飾對象
數(shù)據(jù)類:
export default class YuanZhen {
public name: string = 'YuanZhen';
public age: number = 18;
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
import YuanZhen from './YuanZhen';
export default class Yuan {
public number: number = 1;
public yuanZhen: YuanZhen = new YuanZhen('yuanzhen', 18);
constructor(number: number, yuanZhen: YuanZhen) {
this.number = number
this.yuanZhen = yuanZhen
}
}
?子組件:
import Yuan from './bean/Yuan'
@Component
export default struct ProvideTest {
@Consume yuan:Yuan
build() {
Row() {
Column() {
Text("子name:" + this.yuan.yuanZhen.name+"\nage:"+this.yuan.yuanZhen.age+"\nnumber:"+this.yuan.number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan.number=26
this.yuan.yuanZhen.age=30
this.yuan.yuanZhen.name="袁世震"
})
}.width('100%')
}.height('100%')
}
}
父組件:
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@Provide yuan:Yuan=new Yuan(2,new YuanZhen("袁震",18))
build() {
Column(){
Text("父name:" + this.yuan.yuanZhen.name+"\nage:"+this.yuan.yuanZhen.age+"\nnumber:"+this.yuan.number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan.number=1
this.yuan.yuanZhen.age=32
this.yuan.yuanZhen.name="袁震1"
})
ProvideTest()
}
}
}
運(yùn)行效果:
點(diǎn)擊父name
點(diǎn)擊子name
所以,當(dāng)裝飾的數(shù)據(jù)類型為class或者Object的時(shí)候,可以觀察到賦值和屬性賦值的變化(屬性為Object.keys(observedObject)返回的所有屬性)。
3,裝飾Array
子組件:
import Yuan from './bean/Yuan'
@Component
export default struct ProvideTest {
@Consume yuan:Array<Yuan>
build() {
Row() {
Column() {
Text("子size:" + this.yuan.length+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan[0].number =20
this.yuan[0].yuanZhen.age=35
this.yuan.pop()
})
}.width('100%')
}.height('100%')
}
}
?父組件:
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@Provide yuan:Array<Yuan>=new Array
aboutToAppear(){
let yuan1:Yuan =new Yuan(1,new YuanZhen("袁震1",18))
let yuan2:Yuan =new Yuan(2,new YuanZhen("袁震2",19))
let yuan3:Yuan =new Yuan(3,new YuanZhen("袁震3",20))
this.yuan.push(yuan1)
this.yuan.push(yuan2)
this.yuan.push(yuan3)
}
build() {
Column(){
Text("父size:" + this.yuan.length+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan[0].number =10
this.yuan[0].yuanZhen.age=30
this.yuan.pop()
})
ProvideTest()
}
}
}
?運(yùn)行:
點(diǎn)擊父
點(diǎn)擊子
由此可見,?當(dāng)裝飾的對象是array的時(shí)候,可以觀察到數(shù)組的添加、刪除、更新數(shù)組單元
!注意:更新原理
初始渲染:
- @Provide裝飾的變量會以map的形式,傳遞給當(dāng)前@Provide所屬組件的所有子組件;
- 子組件中如果使用@Consume變量,則會在map中查找是否有該變量名/alias(別名)對應(yīng)的@Provide的變量,如果查找不到,框架會拋出JS ERROR;
- 在初始化@Consume變量時(shí),和@State/@Link的流程類似,@Consume變量會保存在map中查找到的@Provide變量,并把自己注冊給@Provide。
當(dāng)@Provide裝飾的數(shù)據(jù)變化時(shí):
- 通過初始渲染的步驟可知,子組件@Consume已把自己注冊給父組件。父組件@Provide變量變更后,會遍歷更新所有依賴它的系統(tǒng)組件(elementid)和狀態(tài)變量(@Consume);
- 通知@Consume更新后,子組件所有依賴@Consume的系統(tǒng)組件(elementId)都會被通知更新。以此實(shí)現(xiàn)@Provide對@Consume狀態(tài)數(shù)據(jù)同步。
當(dāng)@Consume裝飾的數(shù)據(jù)變化時(shí):
通過初始渲染的步驟可知,子組件@Consume持有@Provide的實(shí)例。在@Consume更新后調(diào)用@Provide的更新方法,將更新的數(shù)值同步回@Provide,以此實(shí)現(xiàn)@Consume向@Provide的同步更新。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-790100.html文章來源:http://www.zghlxwxcb.cn/news/detail-790100.html
?
到了這里,關(guān)于鴻蒙Harmony--狀態(tài)管理器--@Provide裝飾器和@Consume裝飾器詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!