?經(jīng)歷的越多,越喜歡簡單的生活,干凈的東西,清楚的感覺,有結(jié)果的事,和說到做到的人。把圈子變小,把語放緩,把心放寬,用心做好手邊的事兒,該有的總會有的!
目錄
一,定義
二,裝飾器說明
三,變量的傳遞/訪問規(guī)則說明
?四,使用
1,簡單對象的使用
2,嵌套對象的使用
3,數(shù)組對象的使用
一,定義
之前所講的裝飾器僅能觀察到第一層的變化,但是在實際應(yīng)用開發(fā)中,應(yīng)用會根據(jù)開發(fā)需要,封裝自己的數(shù)據(jù)模型。對于多層嵌套的情況,比如二維數(shù)組,或者數(shù)組項class,或者class的屬性是class,他們的第二層的屬性變化是無法觀察到的。這就引出了@Observed/@ObjectLink裝飾器。
@ObjectLink和@Observed類裝飾器用于在涉及嵌套對象或數(shù)組的場景中進行雙向數(shù)據(jù)同步:
①被@Observed裝飾的類,可以被觀察到屬性的變化;
②子組件中@ObjectLink裝飾器裝飾的狀態(tài)變量用于接收@Observed裝飾的類的實例,和父組件中對應(yīng)的狀態(tài)變量建立雙向數(shù)據(jù)綁定。這個實例可以是數(shù)組中的被@Observed裝飾的項,或者是class object中的屬性,這個屬性同樣也需要被@Observed裝飾。
③單獨使用@Observed是沒有任何作用的,需要搭配@ObjectLink或者@Prop使用。
限制條件:
①使用@Observed裝飾class會改變class原始的原型鏈,@Observed和其他類裝飾器裝飾同一個class可能會帶來問題。
②@ObjectLink裝飾器不能在@Entry裝飾的自定義組件中使用。
二,裝飾器說明
@Observed類裝飾器 | 說明 |
---|---|
裝飾器參數(shù) | 無 |
類裝飾器 | 裝飾class。需要放在class的定義前,使用new創(chuàng)建類對象。 |
@ObjectLink變量裝飾器 | 說明 |
---|---|
裝飾器參數(shù) | 無 |
同步類型 | 不與父組件中的任何類型同步變量。 |
允許裝飾的變量類型 | 必須為被@Observed裝飾的class實例,必須指定類型。 不支持簡單類型,可以使用@Prop。 支持繼承Date或者Array的class實例 @ObjectLink的屬性是可以改變的,但是變量的分配是不允許的,也就是說這個裝飾器裝飾變量是只讀的,不能被改變。 |
被裝飾變量的初始值 | 不允許。 |
!注意:
@ObjectLink裝飾的變量不能被賦值,如果要使用賦值操作,請使用@Prop。
①@Prop裝飾的變量和數(shù)據(jù)源的關(guān)系是單向同步,@Prop裝飾的變量在本地拷貝了數(shù)據(jù)源,所以它允許本地更改,如果父組件中的數(shù)據(jù)源有更新,@Prop裝飾的變量本地的修改將被覆蓋;
②@ObjectLink裝飾的變量和數(shù)據(jù)源的關(guān)系是雙向同步,@ObjectLink裝飾的變量相當(dāng)于指向數(shù)據(jù)源的指針。禁止對@ObjectLink裝飾的變量賦值,如果一旦發(fā)生@ObjectLink裝飾的變量的賦值,則同步鏈將被打斷。因為@ObjectLink修飾的變量通過數(shù)據(jù)源(Object)引用來初始化。對于實現(xiàn)雙向數(shù)據(jù)同步的@ObjectLink,賦值相當(dāng)于更新父組件中的數(shù)組項或者class的屬性,TypeScript/JavaScript不能實現(xiàn),會發(fā)生運行時報錯。
三,變量的傳遞/訪問規(guī)則說明
@ObjectLink傳遞/訪問 | 說明 |
---|---|
從父組件初始化 | 必須指定。 初始化@ObjectLink裝飾的變量必須同時滿足以下場景: -?類型必須是@Observed裝飾的class。 -?初始化的數(shù)值需要是數(shù)組項,或者class的屬性。 -?同步源的class或者數(shù)組必須是@State,@Link,@Provide,@Consume或者@ObjectLink裝飾的數(shù)據(jù)。 |
與源對象同步 | 雙向。 |
可以初始化子組件 | 允許,可用于初始化常規(guī)變量、@State、@Link、@Prop、@Provide |
?四,使用
注意,@Observed必須在ets文件中使用,在ts文件中不允許使用
1,簡單對象的使用
用@Observed裝飾數(shù)據(jù)類
@Observed
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 './bean/YuanZhen'
@Component
export default struct ProvideTest {
@ObjectLink yuanZhen:YuanZhen
build() {
Row() {
Column() {
Text("子name:" + this.yuanZhen.name+"\nage:"+this.yuanZhen.age)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuanZhen.name ="袁震2"
this.yuanZhen.age=35
})
}.width('100%')
}.height('100%')
}
}
父組件
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@State yuan:YuanZhen=new YuanZhen("袁震",18)
build() {
Column(){
Text("父name:" + this.yuan.name+"\nage:"+this.yuan.age)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan.name ="袁震1"
this.yuan.age =20
})
ProvideTest({yuanZhen:this.yuan})
}
}
}
注意:這里會有一個報錯,Assigning the '@State' decorated attribute 'yuan' to the '@ObjectLink' decorated attribute 'yuanZhen' is not allowed. <ArkTSCheck> 是編譯器的問題,但是不影響使用
運行效果:
點擊父
點擊子
所以,?被@Observed和@ObjectLink修飾的class可以實現(xiàn)父子雙向綁定
2,嵌套對象的使用
用@Observed修飾的數(shù)據(jù)類:
@Observed
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';
@Observed
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 YuanZhen from './bean/YuanZhen'
@Component
export default struct ProvideTest {
@ObjectLink yuanZhen:YuanZhen
build() {
Row() {
Column() {
Text("子name:" + this.yuanZhen.name+"\nage:"+this.yuanZhen.age)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuanZhen.name ="袁震2"
this.yuanZhen.age=35
})
}.width('100%')
}.height('100%')
}
}
父組件:
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@State yuan:Yuan=new Yuan(1,new YuanZhen("袁震",18))
build() {
Column(){
Text("父name:" + this.yuan.yuanZhen.name+"\nage:"+this.yuan.yuanZhen.age)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan.yuanZhen.name ="袁震1"
this.yuan.yuanZhen.age =20
console.info("yz----name="+this.yuan.yuanZhen.name )
})
ProvideTest({yuanZhen:this.yuan.yuanZhen})
}
}
}
運行:
點擊父
點擊子
點擊父組件,輸出:
由此可見,當(dāng)class為嵌套類型時,父組件的UI不會改變,但是數(shù)據(jù)會改變,子組件的UI和數(shù)據(jù)都會改變
3,數(shù)組對象的使用
子組件
import Yuan from './bean/Yuan'
@Component
export default struct ProvideTest {
@ObjectLink 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.yuanZhen.name ="袁震子組件"
this.yuan.yuanZhen.age=35
console.log("yz---name:"+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 {
@State 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("父name:" + this.yuan[0].yuanZhen.name+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan[0].yuanZhen.name="袁震父組件"
this.yuan[0].number =10
this.yuan[0].yuanZhen.age=30
})
ProvideTest({yuan:this.yuan[0]})
}
}
}
運行:
點擊父
點擊子
可以看到,父組件不會更新本身的UI,會更新子組件的UI,子組件既不會更新自己的UI也不會更新父組件的UI。
但是,可以直接傳給子組件簡單類,這樣可以更新子組件
子組件?
import YuanZhen from './bean/YuanZhen'
@Component
export default struct ProvideTest {
@ObjectLink yuanZhen:YuanZhen
build() {
Row() {
Column() {
Text("子name:"+this.yuanZhen.name+"\nage:"+this.yuanZhen.age)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuanZhen.name ="袁震子組件"
this.yuanZhen.age=35
console.log("yz---name:"+this.yuanZhen.name)
})
}.width('100%')
}.height('100%')
}
}
父組件
import Yuan from './bean/Yuan';
import YuanZhen from './bean/YuanZhen';
import ProvideTest from './ProvideTest';
@Entry
@Component
struct Index {
@State 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("父name:" + this.yuan[0].yuanZhen.name+"\nage:"+this.yuan[0].yuanZhen.age+"\nnumber:"+this.yuan[0].number)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.yuan[0].yuanZhen.name="袁震父組件"
this.yuan[0].number =10
this.yuan[0].yuanZhen.age=30
})
ProvideTest({yuanZhen:this.yuan[0].yuanZhen})
}
}
}
點擊父
點擊子
文章來源:http://www.zghlxwxcb.cn/news/detail-790099.html
父組件的ui不會改變,子組件的UI會實時更新文章來源地址http://www.zghlxwxcb.cn/news/detail-790099.html
到了這里,關(guān)于鴻蒙Harmony--狀態(tài)管理器-@Observed裝飾器和@ObjectLink裝飾器詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!