【鴻蒙 HarmonyOS 4.0】狀態管理

一、介紹

資料來自官網:文檔中心

在聲明式UI編程框架中,UI是程序狀態的運行結果,用戶構建了一個UI模型,其中應用的運行時的狀態是參數。當參數改變時,UI作為返回結果,也將進行對應的改變。這些運行時的狀態變化所帶來的UI的重新渲染,在ArkUI中統稱為狀態管理機制。

  • View(UI):UI渲染,指將build方法內的UI描述和@Builder裝飾的方法內的UI描述映射到界面。
  • State:狀態,指驅動UI更新的數據。用戶通過觸發組件的事件方法,改變狀態數據。狀態數據的改變,引起UI的重新渲染。

二、@State裝飾器:組件內狀態?

@State裝飾的變量,或稱為狀態變量,一旦變量擁有了狀態屬性,就和自定義組件的渲染綁定起來。當狀態改變時,UI會發生對應的渲染改變。

?

說明:

@State裝飾器標記的變量必須初始化,不能為空值

@State支持Object、class、string、number、boolean、enum類型以及這些類型的數組

嵌套類型以及數組中的對象屬性無法觸發視圖更新?

組件傳值代碼示例,為下面不同組件之間傳值做準備:👇

// 任務類
class Task{static id: number = 1// 任務名稱name: string = `任務${Task.id++}`// 任務狀態:是否完成finished: boolean = false
}
// 統一的卡片樣式
@Styles function card(){.width('95%').padding(20).backgroundColor(Color.White).borderRadius(15).shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4})
}@Entry
@Component
struct PropLinkPages {// 總任務數量@State totalTask: number = 0// 已完成任務數量@State finishTask: number = 0// 任務數組@State tasks: Task[] = []//此函數是更新任務總數量和已完成任務數量的handleTaskChange(){// 1.更新任務總數量this.totalTask = this.tasks.length// 2.更新已完成任務數量this.finishTask = this.tasks.filter(item => item.finished).length}build() {Column({space:10}){//1.任務進度卡片Row(){Text('任務進度:').fontSize(30).fontWeight(FontWeight.Bold)Stack(){Progress({value: this.finishTask,total: this.totalTask,type: ProgressType.Ring}).width(100)Row(){Text(this.finishTask.toString()).fontSize(24).fontColor('#36D')Text(' / ' + this.totalTask.toString()).fontSize(24)}}}.card().margin({top: 5, bottom: 10}).justifyContent(FlexAlign.SpaceEvenly)// 2.新增任務按鈕Button('新增任務').width(200).margin({bottom: 10}).onClick(() => {// 1.新增任務數據this.tasks.push(new Task())// 2.更新任務總數量this.handleTaskChange()})//3.任務列表List({space: 10}){ForEach(this.tasks,(item: Task, index) => {ListItem(){Row(){Text(item.name).fontSize(20)Checkbox().select(item.finished).onChange(val => {// 1.更新當前任務狀態item.finished = val// 2.更新已完成任務數量this.handleTaskChange()})}.card().justifyContent(FlexAlign.SpaceBetween)}.swipeAction({end: this.DeleteButton(index)})})}.width('100%').layoutWeight(1).alignListItem(ListItemAlign.Center)}.width('100%').height('100%').backgroundColor('#F1F2F3')}@Builder DeleteButton(index: number){Button(){Image($r('app.media.ic_public_delete_filled')).fillColor(Color.White).width(20)}.width(40).height(40).type(ButtonType.Circle).backgroundColor(Color.Red).margin(5).onClick(() => {this.tasks.splice(index, 1)this.handleTaskChange()})}
}

示例代碼說明:

這是一個展示任務進度的效果,分為任務進度條和任務列表兩部分

對于新增的任務勾選后可在任務進度中查看已勾選和總任務數量,左滑單個任務會出現刪除按鈕,可進行此任務刪除操作

示例代碼的效果:

?

三、父子組件數據同步

3.1、@Prop裝飾器:父子單向同步

@Prop裝飾的變量可以和父組件建立單向的同步關系。@Prop裝飾的變量是可變的,但是變化不會同步回其父組件。

需求:將示例代碼中的任務進度卡片封裝成TaskStatistics組件,在PropLinkPages組件中引入TaskStatistics組件,封裝后再完成數據的同步渲染

上面示例中:

父組件PropLinkPages,子組件TaskStatistics

總任務與已完成任務數據是由父組件進行維護,子組件進行渲染,所以需要父組件將數據傳遞給子組件

?使用@Prop,父子單向同步


@Prop只支持string、number、boolean、enum類型;父組件對象類型,子組件是對象屬性;不可以是數組、any

3.2、@Link裝飾器:父子雙向同步?

@Link裝飾的變量與其父組件中的數據源共享相同的值。

限制條件:@Link裝飾器不能在@Entry裝飾的自定義組件中使用

需求:將示例代碼中對任務數組的操作(新增任務與任務列表)封裝成TaskList組件,在PropLinkPages組件中引入TaskList組件

上面示例中:

父組件PropLinkPages,子組件TaskList

父子雙方都需要使用總認為與已完成任務數據,并且子組件的數據發生變化后需要通知父組件進行變化,因為上一步@Prop時父組件需要將數據傳遞給另一個子組件TaskStatistics,所以涉及到父子雙向數據綁定渲染

?使用@Link,父子雙向同步


父子類型一致:string、number、boolean、enum、object、class,以及他們的數組;

數組中元素增、刪、替換會引起刷新

嵌套類型以及數組中的對象屬性無法觸發視圖更新

?四、后代組件雙向同步

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

@Provide和@Consume,應用于與后代組件的雙向數據同步,應用于狀態數據在多個層級之間傳遞的場景。

需求:示例代碼中分別使用@Prop與@Link進行數據傳遞,需要更改為@Provide和@Consume跨組件數據傳遞

上面示例中:

父組件PropLinkPages,子組件TaskList,子組件TaskStatistics

在父組件中使用@Provide將所需數據傳給兩個子組件,兩個子組件通過使用@Consume去獲取@Provide提供的變量,建立在@Provide和@Consume之間的雙向數據同步

?@Provide和@Consume可以通過相同的變量名或者相同的變量別名綁定,變量類型必須相同。

下面代碼變量名不一致,但具備相同的別名,使用@Provide和@Consume實現跨組件數據同步👇

五、嵌套類對象屬性變化

5.1、@Observed裝飾器和@ObjectLink裝飾器:嵌套類對象屬性變化

對于多層嵌套的情況,比如二維數組,或者數組項class,或者class的屬性是class,他們的第二層的屬性變化是無法觀察到的。這就引出了@Observed/@ObjectLink裝飾器。

限制條件:

a:使用@Observed裝飾class會改變class原始的原型鏈,@Observed和其他類裝飾器裝飾同一個class可能會帶來問題。

b:@ObjectLink裝飾器不能在@Entry裝飾的自定義組件中使用。

需求: 改造任務進度的代碼,當任務完成后,此任務置灰,并有中劃線

實現步驟:

①任務數組對應的元素Task是對象類型,給Task對象添加@Observed裝飾器

②給嵌套的對象上所對應的變量上添加@ObjectLink裝飾器,但源代碼中是方法參數,所以將此段代碼封裝為TaskItem組件,在TaskItem組件中對變量item添加@ObjectLink

問題:子組件需要調父組件的方法,把父組件的方法作為參數傳遞過來,傳遞過程中存在this的丟失

解決:子組件中定義onTaskChange方法,傳遞給父組件時對函數使用bind方法將this傳遞進去

如下:TaskItem({item:item,onTaskChange:this.handleTaskChange.bind(this)})

// 任務類
@Observed
class Task{static id: number = 1// 任務名稱name: string = `任務${Task.id++}`// 任務狀態:是否完成finished: boolean = false
}
// 統一的卡片樣式
@Styles function card(){.width('95%').padding(20).backgroundColor(Color.White).borderRadius(15).shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4})
}
// 任務完成樣式
@Extend(Text) function finishedTask(){.decoration({type:TextDecorationType.LineThrough}).fontColor('#B1B2B1')
}@Entry
@Component
struct PropLinkPages {// 總任務數量@Provide totalTask: number = 0// 已完成任務數量@Provide finishTask: number = 0build() {Column({space:10}){//1.任務進度卡片TaskStatistics()//2.任務列表TaskList()}.width('100%').height('100%').backgroundColor('#F1F2F3')}
}@Component
struct TaskList {// 任務數組@State tasks: Task[] = []@Consume totalTask: number@Consume finishTask: number//此函數是更新任務總數量和已完成任務數量的handleTaskChange(){// 1.更新任務總數量this.totalTask = this.tasks.length// 2.更新已完成任務數量this.finishTask = this.tasks.filter(item => item.finished).length}build() {Column(){// 2.新增任務按鈕Button('新增任務').width(200).margin({bottom: 10}).onClick(() => {// 1.新增任務數據this.tasks.push(new Task())// 2.更新任務總數量this.handleTaskChange()})//3.任務列表List({space: 10}){ForEach(this.tasks,(item: Task, index) => {ListItem(){TaskItem({item:item,onTaskChange:this.handleTaskChange.bind(this)})}.swipeAction({end: this.DeleteButton(index)})})}.width('100%').layoutWeight(1).alignListItem(ListItemAlign.Center)}}@Builder DeleteButton(index: number){Button(){Image($r('app.media.ic_public_delete_filled')).fillColor(Color.White).width(20)}.width(40).height(40).type(ButtonType.Circle).backgroundColor(Color.Red).margin(5).onClick(() => {this.tasks.splice(index, 1)this.handleTaskChange()})}
}@Component
struct TaskStatistics {@Consume totalTask: number@Consume finishTask: numberbuild() {Row(){Text('任務進度:').fontSize(30).fontWeight(FontWeight.Bold)Stack(){Progress({value: this.finishTask,total: this.totalTask,type: ProgressType.Ring}).width(100)Row(){Text(this.finishTask.toString()).fontSize(24).fontColor('#36D')Text(' / ' + this.totalTask.toString()).fontSize(24)}}}.card().margin({top: 5, bottom: 10}).justifyContent(FlexAlign.SpaceEvenly)}
}@Component
struct TaskItem {@ObjectLink item: TaskonTaskChange: () => voidbuild() {Row(){if(this.item.finished){Text(this.item.name).finishedTask()}else{Text(this.item.name)}Checkbox().select(this.item.finished).onChange(val => {// 1.更新當前任務狀態this.item.finished = val// 2.更新已完成任務數量this.onTaskChange()})}.card().justifyContent(FlexAlign.SpaceBetween)}
}

實現效果:

最后:👏👏😊😊😊👍👍

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697568.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697568.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697568.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Stable Diffusion 模型的概念、類型、下載、安裝、使用

本文收錄于《AI繪畫從入門到精通》專欄,專欄總目錄:點這里。 大家好,我是水滴~~ 我們在《Stable Diffusion WebUI 界面介紹》 時,第一個就講到了 Stable Diffusion 模型,那么這個模型是什么?該從哪兒下載&…

多輸入分類|GWO-CNN-LSTM|灰狼算法優化的卷積-長短期神經網絡分類預測(Matlab)

目錄 一、程序及算法內容介紹: 基本內容: 亮點與優勢: 二、實際運行效果: 三、算法介紹: 灰狼優化算法: 卷積神經網絡-長短期記憶網絡: 四、完整程序下載: 一、程序及算法內容…

【EI會議征稿通知】第五屆人工智能與機電自動化國際學術會議(AIEA 2024)

第五屆人工智能與機電自動化國際學術會議(AIEA 2024) 2024 5th International Conference on Artificial Intelligence and Electromechanical Automation 優秀評選已啟動,設置優秀論文、優秀報告及優秀海報多個獎項,豐厚獎金等…

【Java程序設計】【C00280】基于Springboot的校友社交系統(有論文)

基于Springboot的校友社交系統(有論文) 項目簡介項目簡介項目獲取開發環境項目技術運行截圖 項目簡介 項目簡介 這是一個基于Springboot的校友社交系統 本系統分為系統功能模塊、管理員功能模塊以及用戶功能模塊。 系統功能模塊:在系統首頁…

數據結構與算法——排序算法

目錄 文章目錄 前言 一.排序的基本概念 1.什么是就地排序 2.什么是內部排序和外部排序 3.什么是穩定排序 4.判定一個排序算法的是穩定的 二.插入排序算法 1.直接插入排序 1.1基本思想 1.2復雜度 1.3穩定性 1.4代碼演示 2.折半插入排序 2.1基本思想 2.2性能 3.…

vue實現遞歸組件

父組件&#xff1a; <Tree :data"data"></Tree> import Tree from "/components/Tree.vue"; const data reactive([{name: "1",checked: true,children: [{name: "1-1",checked: false,},],},&#xff09; 子組件&#…

若依logback日志配置采坑

問題描述 若依使用的appender過濾器是level&#xff0c;如下述代碼&#xff0c;這種過濾器只能導出級別為INFO的日志&#xff0c;warn和error都導出不出來。查詢不是很方便。 <!-- 系統日志輸出 --><appender name"file_info" class"ch.qos.logback.…

JAVA IDEA 項目打包為 jar 包詳解

前言 如下簡單 maven 項目&#xff0c;現在 maven 項目比較流行&#xff0c;你還沒用過就OUT了。需要打包jar 先設置&#xff1a;點擊 File > Project Structure > Artifacts > 點擊加號 > 選擇JAR > 選擇From modules with dependencies 一、將所有依賴和模…

VirtualBox+Vagrant快速搭建Centos7

目錄 安裝VirtualBox&#xff1a; 安裝Vagrant&#xff1a; 創建Vagrant項目目錄&#xff1a; 初始化Vagrant配置文件&#xff1a; 本地Vagrantfile中的鏡像名稱&#xff1a; 啟動虛擬機&#xff1a; SSH登錄虛擬機&#xff1a; 備注&#xff1a;安裝鏡像的另一種方式是…

springmvc+ssm+springboot房屋中介服務平臺的設計與實現 i174z

本論文擬采用計算機技術設計并開發的房屋中介服務平臺&#xff0c;主要是為用戶提供服務。使得用戶可以在系統上查看房屋出租、房屋出售、房屋求購、房屋求租&#xff0c;管理員對信息進行統一管理&#xff0c;與此同時可以篩選出符合的信息&#xff0c;給筆者提供更符合實際的…

Autodesk CAD如何建立圖層方框?

在AutoCAD中&#xff0c;要建立圖層方框&#xff08;Layer Box&#xff09;可以通過以下步驟實現&#xff1a; 打開圖層管理器&#xff1a; 在 AutoCAD 中&#xff0c;您可以通過輸入“LA”命令或在菜單欄中選擇“格式” > “圖層管理器”來打開圖層管理器對話框。 創建新圖…

記阿里云mysql丟表丟數據的實踐記錄

第一時間掛工單&#xff0c;聯系工程師指引&#xff0c;現在回過來想&#xff0c;第一時間要確認發生時間。 1.通過性能視圖&#xff08;馬后炮的總結&#xff0c;實際憑記憶恢復了三四次才找到數據&#xff09; 2.先恢復數據 通過Navicat工具&#xff0c;結構同步&#xff0…

解決IntelliJ IDEA 2023版本創建Spring項目時Java只能選擇17或21的問題

問題描述&#xff1a; 當使用IntelliJ IDEA2023版本中Spring Initializr新建Spring項目時&#xff0c;即使JDK配置項為1.8&#xff0c;Java配置項仍然只能選17或21. 在JDK為1.8版本情況下&#xff0c;Java選擇17或21&#xff0c;點擊NEXT按鈕&#xff0c;則會彈窗提示SDK不支持…

Sora: 開啟AI視頻創作的新紀元

隨著人工智能技術的飛速進步&#xff0c;AI視頻模型已迅速成為科技界的新焦點。在這股創新浪潮中&#xff0c;OpenAI推出的Sora&#xff0c;不僅以其前所未有的性能吸引了全球的目光&#xff0c;更以前瞻性的技術定義了AI視頻領域的未來。Sora不僅是一個里程碑式的產品&#xf…

java面試題之SpringMVC篇

Spring MVC的工作原理 Spring MVC的工作原理如下&#xff1a; DispatcherServlet 接收用戶的請求找到用于處理request的 handler 和 Interceptors&#xff0c;構造成 HandlerExecutionChain 執行鏈找到 handler 相對應的 HandlerAdapter執行所有注冊攔截器的preHandler方法調…

音視頻面試題集錦

下面是音視頻開發面試題精選&#xff1a; 1、談談 iOS 音視頻采集相關接口和數據結構的設計&#xff1f;2、如何降低處理音視頻鏈路中的內存峰值&#xff1f;3、OpenGL 如何實現二分屏效果&#xff1f;4、使用 OpenGL 繪制時對于二維坐標需要注意什么&#xff1f; 1、談談 iO…

Vue中如何使用dayjs

Day.js中文網Day.js是一個極簡的JavaScript庫&#xff0c;可以為現代瀏覽器解析、驗證、操作和顯示日期和時間。https://dayjs.fenxianglu.cn/ 單位不區別大小寫&#xff0c;支持復數和縮寫形式 單位縮寫描述 date D日期 [1,31]dayd星期 [0,6]&#xff08;星期日0&#xff0c…

云計算面試題【后期】

前言&#xff1a; 隨著年齡的增長生活瑣碎的事情、煩心的事情日漸增多&#xff0c;怠慢了更新&#xff0c; 1.什么是數據庫 DB.DataBase 數據庫&#xff1a; 依照某種數據模型進行組織并存放到存儲器的數據集合 DBMS.DataBase Management System – 數據庫管理系統&#xff1a;…

Java MP3轉PCM

Java MP3轉PCM 1 添加依賴2 Java 代碼 1 添加依賴 <dependency><groupId>com.googlecode.soundlibs</groupId><artifactId>mp3spi</artifactId><version>1.9.5.4</version> </dependency>2 Java 代碼 package com.xu.music.…

迪蕭科技有限公司邀您參觀2024生物發酵展

參展企業介紹 浙江迪蕭科技有限公司位于浙江杭州&#xff0c;是一家專注于膜技術的國家高新企業。公司針對食品飲料、醫藥保健等領域的過程分離與控制、產品提取及濃縮、廢料資源化利用等提供全方案解決服務。堅持以“顧客至上、優質服務、卓越品質”為原則。為客戶企業提供清…