做網(wǎng)站重要標(biāo)簽成都seo優(yōu)化排名推廣
組件狀態(tài)管理
一、@State
@State用于裝飾當(dāng)前組件的狀態(tài)變量,@State裝飾的變量在發(fā)生變化時,會驅(qū)動當(dāng)前組件的視圖刷新,語法如下:
@State count:number = 1;
需要注意的是:@State裝飾的變量必須進(jìn)行本地初始化。
允許裝飾的類型
基本類型:string、number、boolean、enum
對象類型:json對象、class的實(shí)例對象、
數(shù)組類型:上面所有類型的數(shù)組
能夠觀察到的變化
注意:
并不是狀態(tài)變量的所有更改都會引起UI的刷新
只有可以被框架觀察到的修改才會引起UI刷新
屬性本身的改變都可以 (無論什么類型)
對象:能監(jiān)視對象的直接屬性變化,不能監(jiān)視嵌套屬性的改變
數(shù)組:能監(jiān)視數(shù)組中元素的變化,不能監(jiān)視元素對象內(nèi)部的變化
測試:
定義對象和數(shù)組的狀態(tài)和顯示數(shù)據(jù)
@State @Watch('onChange')obj: {a: {b: number}} = {a: {b: 1}}
@State @Watch('onChange2')arr: {a: number}[] = [{a: 1}]
Text('state.obj' + JSON.stringify(this.obj)).fontSize(18)
Text('state.arr' + JSON.stringify(this.arr)).fontSize(18)
修改屬性對象
this.obj = {a: {b: 2}} // 修改屬性本身 => 能監(jiān)視
this.obj.a = {b: 3} // 修改屬性對象的直接屬性 =》 能監(jiān)視
this.obj.a.b = 4 // 修改屬性對象的嵌套屬性 =》 不能監(jiān)視到
修改屬性數(shù)組
this.arr = [] // 修改屬性本身 => 能監(jiān)視
this.arr[0] = {a: 2} // 修改屬性數(shù)組的元素 => 能監(jiān)視
this.arr.push({a: 3}) // 修改屬性數(shù)組的元素 => 能監(jiān)視
this.arr[0].a = 4 // 修改屬性數(shù)組的元素對象內(nèi)部屬性 =》 不能監(jiān)視
二、@Prop
@Prop用于裝飾子組件的狀態(tài)變量,@Prop裝飾的變量會同步父組件的狀態(tài),但只能單向同步,也就是父組件的狀態(tài)變化會自動同步到子組件,而子組件的變化不會同步到父組件。
父組件
@Entry
@Component
struct Parent{@State count:number = 1;build(){Column(){Child({count:this.count});}}
}
子組件
@Component
export struct Child{@Prop count:number;build(){Text('prop.count: ' + this.count);}
}
需要注意的是:@Prop裝飾的變量不允許本地初始化,只能通過父組件傳參進(jìn)行初始化。
允許裝飾的類型
官方文檔:只允許基本類型,不允許對象和數(shù)組
實(shí)際情況:與@State一致,可以是對象、數(shù)組
能夠觀察到的變化
與@State一致
三、@Link
@Link用于裝飾子組件的狀態(tài)變量,@Prop變量同樣會同步父組件狀態(tài),但是能夠雙向同步。也就是父組件的變化會同步到子組件,而子組件的變化也會同步到父組件。
父組件
@Entry
@Component
struct Parent{@State count:number = 1;build(){Column(){Child({count: $count});}}
}
子組件
@Component
export struct Child{@Link count:number;build(){Text('link.count: ' + this.count);}
}
需要注意的是:@Link裝飾的變量不允許本地初始化,只能由父組件通過傳參進(jìn)行初始化,并且父組件必須使用$變量名的方式傳參,以表示傳遞的是變量的引用。
允許裝飾的類型
與@State一致
框架能夠觀察到的變化
與@State一致
四、@Provide 與 @Consume
@Provide和@Consume用于跨層級傳遞狀態(tài)信息,其中@Provide用于裝飾祖先組件的狀態(tài)變量,@Consume用于裝飾后代組件的狀態(tài)變量。可以理解為祖先組件提供(Provide)狀態(tài)信息供后代組件消費(fèi)(Consume),并且祖先和后代的狀態(tài)信息可以實(shí)現(xiàn)雙向同步。
注意:
@Provide裝飾變量必須本地初始化,而@Consume裝飾的變量不允許本地初始化。
@Provide & @Consume處理的狀態(tài)數(shù)據(jù)是雙向同步的
祖先組件
@Entry
@Component
struct GrandParent {@Provide count: number = 1;@Provide('msg') message: string = '老A';build() {Column() {...}}
}
后代組件
@Entry
@Component
export struct Child {@Consume count: number;@Consume('msg') childMsg: string;build() {Column() {Text('Consume.count: ' + this.count);Text('Consume.childMsg: ' + this.childMsg);}}
}
允許裝飾的類型
與@State一致
能夠觀察到的變化
與@State一致
測試:
@Component
export default struct Child1 {@Prop obj1: {a: {b: number}}@Prop arr1: {a: number}[]update() {// this.obj1 = {a: {b: 3}} // 修改屬性本身 => 能監(jiān)視// this.obj1.a = {b: 4} // 修改屬性對象的直接屬性 =》 能監(jiān)視// setTimeout(() => {// this.obj1.a.b = 9 // 修改屬性對象的嵌套屬性 =》 不能監(jiān)視到 報錯(且會報錯,導(dǎo)致程序退出)// }, 1000)// this.arr1 = [] // 修改屬性本身 => 能監(jiān)視// this.arr1[0] = {a: 5} // 修改屬性數(shù)組的元素 => 能監(jiān)視this.arr1.push({a: 8}) // 修改屬性數(shù)組的元素 => 能監(jiān)視setTimeout(() => {this.arr1[0].a = 5 // 修改屬性數(shù)組的元素對象內(nèi)部屬性 =》 不能監(jiān)視(且會報錯,導(dǎo)致程序退出)}, 1000)}build() {Column({space: 10}) {Text('prop.obj' + JSON.stringify(this.obj1)).fontSize(18)Text('prop.arr' + JSON.stringify(this.arr1)).fontSize(18)Button('開始更新 prop').onClick(() => this.update())}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
@Component
export default struct Child2 {@Link obj2: {a: {b: number}}@Link arr2: {a: number}[]update () {// this.obj1 = {a: {b: 2}} // 修改屬性本身 => 能監(jiān)視// this.obj2.a = {b: 4} // 修改屬性對象的直接屬性 =》 能監(jiān)視// setTimeout(() => {// this.obj2.a.b = 9 // 修改屬性對象的嵌套屬性 =》 不能監(jiān)視到// })// this.arr2 = [] // 修改屬性本身 => 能監(jiān)視// this.arr2[0] = {a: 3} // 修改屬性數(shù)組的元素 => 能監(jiān)視this.arr2.push({a: 5}) // 修改屬性數(shù)組的元素 => 能監(jiān)視setTimeout(() => {this.arr2[0].a = 4 // 修改屬性數(shù)組的元素對象內(nèi)部屬性 =》 不能監(jiān)視})}build() {Column({space: 10}) {Text('link.obj2' + JSON.stringify(this.obj2)).fontSize(18)Text('link.arr2' + JSON.stringify(this.arr2)).fontSize(18)Button('開始更新 link').onClick(() => this.update())}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
import Child1 from './Child1'
import Child2 from './Child2'
@Entry
@Component
struct StateTest {@State obj: {a: {b: number}} = {a: {b: 1}}@State arr: {a: number}[] = [{a: 1}]update() {// this.obj = {a: {b: 1}} // 修改屬性本身 => 能監(jiān)視// this.obj.a = {b: 2} // 修改屬性對象的直接屬性 =》 能監(jiān)視// setTimeout(() => {// this.obj.a.b = 6 // 修改屬性對象的嵌套屬性 =》 不能監(jiān)視到// }, 1000)// this.arr = [] // 修改屬性本身 => 能監(jiān)視// this.arr[0] = {a: 2} // 修改屬性數(shù)組的元素 => 能監(jiān)視this.arr.push({a: 3}) // 修改屬性數(shù)組的元素 => 能監(jiān)視setTimeout(() => {this.arr[0].a = 9 // 修改屬性數(shù)組的元素對象內(nèi)部屬性 =》 不能監(jiān)視}, 1000)}build() {Column({space: 10}) {Text('state.obj' + JSON.stringify(this.obj)).fontSize(18)Text('state.arr' + JSON.stringify(this.arr)).fontSize(18)Button('開始更新2 state').onClick(() => this.update())Child1({obj1: this.obj, arr1: this.arr})Child2({obj2: $obj, arr2: $arr})}.width('100%').padding(20)}
}
五、@Watch
用來監(jiān)視狀態(tài)數(shù)據(jù)的變化,包括:@State、@Prop、@Link、@Provide、@Consume
一旦狀態(tài)數(shù)據(jù)變化,監(jiān)視的回調(diào)就會調(diào)用
我們可以在監(jiān)視的回調(diào)中執(zhí)行應(yīng)用需要的特定邏輯
以@State為例編碼
@State @Watch('onCountChange') count: number = 0
/*** 一旦count變化,此回調(diào)函數(shù)就會自動調(diào)用* @param name 被監(jiān)視的狀態(tài)屬性名*/
onCountChange (name) {// 可以在此做特定處理
}
測試
@Component
export default struct Child1 {@Prop count1: numberbuild() {Column({space: 10}) {Row({space: 10}) {Text('prop.count1: ' + this.count1).fontSize(18)Button('更新prop.count1').onClick(() => this.count1 += 1)}}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
@Component
export default struct Child2 {@Link count2: numberbuild() {Column({space: 10}) {Row({space: 10}) {Text('link.count2: ' + this.count2).fontSize(18)Button('開始更新link.count2').onClick(() => this.count2 += 1)}}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
import GrandChild from './GrandChild'
@Component
export default struct Child3 {build() {Column({space: 10}) {GrandChild()}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
import promptAction from '@ohos.promptAction'
@Component
export default struct GrandChild {@Consume @Watch('onMsgChange') msg: stringonMsgChange () {promptAction.showToast({message: this.msg})}build() {Column({space: 10}) {Text('Consume.msg: ' + this.msg).fontSize(18)Button('開始更新Consume.count2').onClick(() => this.msg += '--')}.width('100%').padding(20).border({width: 1, color: Color.Gray})}
}
import Child1 from './Child1'
import Child2 from './Child2'
import promptAction from '@ohos.promptAction'
import Child3 from './Child3'
@Entry
@Component
struct StateBaseTest {@State @Watch('onCountChange') count: number = 0@Provide msg: string = 'abc'/*** 一旦count變化,此回調(diào)函數(shù)就會自動調(diào)用* @param name 被監(jiān)視的狀態(tài)屬性名*/onCountChange (name) {if (this.count>3) {promptAction.showToast({message: `當(dāng)前count為${this.count},已經(jīng)超過了3`})}}build() {Column({space: 10}) {Row({space: 10}) {Text('state.count: ' + this.count).fontSize(18)Button('更新state.count').onClick(() => this.count += 1)}Text('count值超過3,每次更新都提示一下').fontColor(Color.Orange)Child1({count1: this.count})Child2({count2: $count})Divider()Text('provide.msg: ' + this.msg).fontSize(18)Button('開始更新provide.msg').onClick(() => this.msg += '++')Child3()}.width('100%').padding(20)}
}
六、@ObjectLink 和 @Observed
前面的問題:
● 屬性對象中的嵌套對象的屬性修改不能監(jiān)視到,也就不會自動更新UI
● 屬性數(shù)組中的元素對象的屬性修改不能監(jiān)視到,也就不會自動更新UI
● @Props與@Link聲明接收的屬性,必須是@State的屬性,而不能是@State屬性對象中嵌套的屬性
解決辦法
● 將嵌套對象的類型用class定義, 并使用@Observed來裝飾
● 子組件中定義的嵌套對象的屬性, 使用@ObjectLink來裝飾
測試:
@Observed
class Person2 {id: number;name: string;age: number;constructor(id, name, age) {this.id = idthis.name = namethis.age = age}
}
@Component
struct PersonItem {// @Prop person: Person// @Link person: Person@ObjectLink person: Person2build() {Row() {Text(JSON.stringify(this.person)).fontSize(20)Button('更新年齡').onClick(() => this.person.age += 2)}.border({width: 1, color: Color.Gray}).padding(10)}
}
@Entry
@Component
struct PersonList {@State persons: Person2[] = [new Person2(1, 'Tom', 12),new Person2(2, 'Jack', 13),]build() {Column({space: 10}){Button('更新嵌套對象的屬性:一個人的年齡').onClick(() => {this.persons[0].age++})List() {ForEach(this.persons, (item: Person2, index: number) => {ListItem(){PersonItem({person: item})}})}}.padding(20)}
}
以上就是常用組件狀態(tài)說明
為了幫助大家更深入有效的學(xué)習(xí)到鴻蒙開發(fā)知識點(diǎn),小編特意給大家準(zhǔn)備了一份全套最新版的HarmonyOS NEXT學(xué)習(xí)資源,獲取完整版方式請點(diǎn)擊→《HarmonyOS教學(xué)視頻》
HarmonyOS教學(xué)視頻:語法ArkTS、TypeScript、ArkUI等.....視頻教程
鴻蒙生態(tài)應(yīng)用開發(fā)白皮書V2.0PDF:
獲取完整版白皮書方式請點(diǎn)擊→《鴻蒙生態(tài)應(yīng)用開發(fā)白皮書V2.0PDF》
鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊
一、入門必看
- 應(yīng)用開發(fā)導(dǎo)讀(ArkTS)
- ……
二、HarmonyOS 概念
- 系統(tǒng)定義
- 技術(shù)架構(gòu)
- 技術(shù)特性
- 系統(tǒng)安全
- ........
三、如何快速入門?《做鴻蒙應(yīng)用開發(fā)到底學(xué)些啥?》
- 基本概念
- 構(gòu)建第一個ArkTS應(yīng)用
- ……
四、開發(fā)基礎(chǔ)知識
- 應(yīng)用基礎(chǔ)知識
- 配置文件
- 應(yīng)用數(shù)據(jù)管理
- 應(yīng)用安全管理
- 應(yīng)用隱私保護(hù)
- 三方應(yīng)用調(diào)用管控機(jī)制
- 資源分類與訪問
- 學(xué)習(xí)ArkTS語言
- ……
五、基于ArkTS 開發(fā)
- Ability開發(fā)
- UI開發(fā)
- 公共事件與通知
- 窗口管理
- 媒體
- 安全
- 網(wǎng)絡(luò)與鏈接
- 電話服務(wù)
- 數(shù)據(jù)管理
- 后臺任務(wù)(Background Task)管理
- 設(shè)備管理
- 設(shè)備使用信息統(tǒng)計
- DFX
- 國際化開發(fā)
- 折疊屏系列
- ……
更多了解更多鴻蒙開發(fā)的相關(guān)知識可以參考:《鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊》