【HarmonyOS4學習筆記】《HarmonyOS4+NEXT星河版入門到企業級實戰教程》課程學習筆記(十)

課程地址: 黑馬程序員HarmonyOS4+NEXT星河版入門到企業級實戰教程,一套精通鴻蒙應用開發

(本篇筆記對應課程第 17 節)

P17《16.Ark-狀態管理@Prop @Link @Provide @Consume》

將上一節寫出的代碼進行功能模塊封裝:1、任務進度卡片為一個組件;2、新增任務按鈕與任務列表展示為一個組件

1、任務進度卡片抽取為一個組件
在這里插入圖片描述

2、使用這個組件并傳遞參數,此時 struct PropPage為父組件, TaskStatistics 為子組件。傳遞參數這里報錯了:因為父組件和子組件里同時都用 @State 裝飾器聲明了同樣的變量。

在這里插入圖片描述

將子組件中聲明變量前的 @State 去掉,發現不報錯了:

在這里插入圖片描述

此時發現父組件中數據變化了,但子組件并不知道這些數據變化了:

在這里插入圖片描述

如需要父組件與子組件中的數據進行聯動,就需要使用 @Prop 或者 @Link 裝飾器。兩者之間的區別是:@Prop 是數據的單向同步,即只會在父組件中修改數據影響子組件,反之不會;實現原理是將數據copy了一份傳遞給了子組件;而 @Link是數據的雙向同步,父組件修改數據會影響子組件,子組件中修改數據也會影響父組件,實現原理是將數據的引用傳遞給了子組件,父組件與子組件修改的是同一份數據

在這里插入圖片描述

在子組件中的變量前加上@Prop 裝飾,此時發現提示:**@Prop 修飾的變量不能再初始化。因為@Prop是期望父組件傳遞過來數據,所以不需要再自己初始化了。**刪去初始化賦值。

在這里插入圖片描述

此時發現任務管理子組件中的數據可以更新了。這樣就實現了父組件到子組件的單向數據聯動。

在這里插入圖片描述

將新增任務與任務列表部分抽取為子組件:將其需要的state數據、操作數據的方法以及自定義的構建函數 deleteBtn 全部放到這個子組件中去,因為它使用到了這些功能:

在這里插入圖片描述

在這里插入圖片描述

使用這個子組件并且父組件中向其傳遞參數:

在這里插入圖片描述

子組件中相應的數據改為 @Prop 聲明:

在這里插入圖片描述

由于需要在子組件中也改變 總任務數量與已完成任務數量的值,所以需要用 @Link 傳遞這兩個數據:

在這里插入圖片描述

此時發現父組件中傳遞數據報錯了:

在這里插入圖片描述

因為 @Link 需要傳遞一個引用給子組件,用變量前面加上 $ 的方式代表傳遞這個變量的引用,這樣子組件對數據的修改父組件也可以感知到了:

在這里插入圖片描述

如果子組件不需要對數據進行修改,只用數據做渲染展示,那么使用 @Prop 傳遞;如果子組件需要對數據進行修改,那么使用 @Link 傳遞。

官方文檔中寫 @Prop可以初始化,還寫 @Prop 允許父組件是 數組,兒子是元素,但實際上是不行的!
在這里插入圖片描述

驗證一下對象類型:

在這里插入圖片描述

用 @Prop 裝飾一個對象類型數據,會發現有提示:@Prop 裝飾的數據必須是 string、number、boolean類型。

在這里插入圖片描述

在這里插入圖片描述

@Link 是允許傳遞對象的:

在這里插入圖片描述

在這里插入圖片描述

@Link 支持傳遞對象類型,而@Prop不支持傳遞對象類型,但可以傳遞對象的屬性。

@Provide 與 @Consume :
在這里插入圖片描述

父組件中改為 @Provide,子組件中改為 @Consume,此時發現報錯了:

在這里插入圖片描述

因為@Provide不需要顯示傳遞參數,將傳參去掉:

在這里插入圖片描述

同時子組件中使用 @Consume 來接收:

在這里插入圖片描述

@Prop 與 @Link 的選擇:如果子組件不需要修改數據,只用數據來渲染展示,則使用 @Prop ;如果子組件需要修改數據,則使用 @Link。

@Provide @Consume 與 @Prop @Link 的選擇:如果是父子組件傳遞,沒必要使用@Provide @Consume ,因為它不需要顯示傳遞參數,內部做了維護,肯定會造成一些性能的損耗;所以父子組件間傳遞盡量使用 @Prop @Link ;跨級組件傳遞可以使用 @Provide @Consume 。

注意:@Provide @Consume 祖組件與后代組件中傳遞的數據是雙向同步的。

在這里插入圖片描述

實踐:

1、拆分子組件并使用 @Prop @Link 傳遞數據:


class Task {static id:number = 1// 任務名稱name:string = `任務${Task.id++}`// 任務狀態:是否完成finished:boolean = false
}@Styles function cardStyle(){.width('100%').height(120).padding(10).backgroundColor('#fff').borderRadius(8)
}@Entry
@Component
struct Index {// 總任務數量@State totalTask:number = 0// 已完成任務數量@State finishTask:number = 0// 任務列表@State tasks:Task[] = []build() {Row() {Column() {// 1、任務進度卡片TaskStatistics({ totalTask:this.totalTask, finishTask:this.finishTask })// 2、使用任務列表子組件TaskList({ totalTask:$totalTask, finishTask:$finishTask })}.width('100%').height('100%').justifyContent(FlexAlign.Start)}.height('100%').width('100%').padding({top:20,bottom :20, left:10,right:10}).backgroundColor('#efefef')}}// 任務進度卡片子組件
@Component
struct TaskStatistics{@Prop finishTask:number@Prop totalTask:numberbuild(){Row(){Text('任務進度:').fontSize(22).fontWeight(FontWeight.Bold)Stack(){Progress({value : this.finishTask,total : this.totalTask,type : ProgressType.Ring})Row(){Text(this.finishTask.toString())Text(`/${this.totalTask.toString()}`)}}}.cardStyle().justifyContent(FlexAlign.SpaceEvenly)}
}// 新增任務與任務列表子組件
@Component
struct TaskList{// 總任務數量@Link totalTask:number// 已完成任務數量@Link finishTask:number// 任務列表@State tasks:Task[] = []handleTaskChange(){// 更新任務總數量this.totalTask = this.tasks.length// 更新已完成任務數量this.finishTask = this.tasks.filter(item => item.finished).length}build() {Column(){// 2、新增任務按鈕Button('新增任務').width(200).margin({top:20, bottom:20}).onClick(()=>{// 新增任務this.tasks.push(new Task())// 更新任務總數量// this.totalTask = this.tasks.lengththis.handleTaskChange()})// 3、任務列表展示List(){ForEach(this.tasks,(item:Task,index)=>{ListItem(){Row(){Text(item.name)Checkbox().select(item.finished).onChange(val => {// 更新任務狀態item.finished = val// 更新已完成任務數量// this.finishTask = this.tasks.filter(item => item.finished).lengththis.handleTaskChange()})}.cardStyle().height(60).margin({bottom:10}).justifyContent(FlexAlign.SpaceBetween)}.swipeAction({ end: this.deleteBtn(index)})})}.layoutWeight(1)}}@Builder deleteBtn(index){Button(){Image($r('app.media.icon_delete')).width(30).fillColor(Color.Red)}.width(40).height(40).type(ButtonType.Circle).backgroundColor(Color.Red).margin(6).onClick(() => {this.tasks.splice(index,1)this.handleTaskChange()})}
}

2、驗證 @Prop 不支持對象類型,僅支持對象屬性的傳遞;而 @Link 支持傳遞對象類型:


class Task {static id:number = 1// 任務名稱name:string = `任務${Task.id++}`// 任務狀態:是否完成finished:boolean = false
}class Stat {// 總任務數量totalTask:number = 0// 已完成任務數量finishTask:number = 0
}@Styles function cardStyle(){.width('100%').height(120).padding(10).backgroundColor('#fff').borderRadius(8)
}@Entry
@Component
struct Index {// 總任務數量// @State totalTask:number = 0// 已完成任務數量// @State finishTask:number = 0@State stat:Stat = new Stat()// 任務列表@State tasks:Task[] = []build() {Row() {Column() {// 1、任務進度卡片TaskStatistics({ totalTask:this.stat.totalTask, finishTask:this.stat.finishTask })// 2、使用任務列表子組件// TaskList({ totalTask:$totalTask, finishTask:$finishTask })TaskList({ stat:$stat })}.width('100%').height('100%').justifyContent(FlexAlign.Start)}.height('100%').width('100%').padding({top:20,bottom :20, left:10,right:10}).backgroundColor('#efefef')}}// 任務進度卡片子組件
@Component
struct TaskStatistics{@Prop finishTask:number@Prop totalTask:numberbuild(){Row(){Text('任務進度:').fontSize(22).fontWeight(FontWeight.Bold)Stack(){Progress({value : this.finishTask,total : this.totalTask,type : ProgressType.Ring})Row(){Text(this.finishTask.toString())Text(`/${this.totalTask.toString()}`)}}}.cardStyle().justifyContent(FlexAlign.SpaceEvenly)}
}// 新增任務與任務列表子組件
@Component
struct TaskList{// 總任務數量// @Link totalTask:number// 已完成任務數量// @Link finishTask:number@Link stat:Stat// 任務列表@State tasks:Task[] = []handleTaskChange(){// 更新任務總數量// this.totalTask = this.tasks.lengththis.stat.totalTask = this.tasks.length// 更新已完成任務數量// this.finishTask = this.tasks.filter(item => item.finished).lengththis.stat.finishTask = this.tasks.filter(item => item.finished).length}build() {Column(){// 2、新增任務按鈕Button('新增任務').width(200).margin({top:20, bottom:20}).onClick(()=>{// 新增任務this.tasks.push(new Task())// 更新任務總數量// this.totalTask = this.tasks.lengththis.handleTaskChange()})// 3、任務列表展示List(){ForEach(this.tasks,(item:Task,index)=>{ListItem(){Row(){Text(item.name)Checkbox().select(item.finished).onChange(val => {// 更新任務狀態item.finished = val// 更新已完成任務數量// this.finishTask = this.tasks.filter(item => item.finished).lengththis.handleTaskChange()})}.cardStyle().height(60).margin({bottom:10}).justifyContent(FlexAlign.SpaceBetween)}.swipeAction({ end: this.deleteBtn(index)})})}.layoutWeight(1)}}@Builder deleteBtn(index){Button(){Image($r('app.media.icon_delete')).width(30).fillColor(Color.Red)}.width(40).height(40).type(ButtonType.Circle).backgroundColor(Color.Red).margin(6).onClick(() => {this.tasks.splice(index,1)this.handleTaskChange()})}
}

3、使用 @Provide 和 @Consume:


class Task {static id:number = 1// 任務名稱name:string = `任務${Task.id++}`// 任務狀態:是否完成finished:boolean = false
}class Stat {// 總任務數量totalTask:number = 0// 已完成任務數量finishTask:number = 0
}@Styles function cardStyle(){.width('100%').height(120).padding(10).backgroundColor('#fff').borderRadius(8)
}@Entry
@Component
struct Index {// 總任務數量// @State totalTask:number = 0// 已完成任務數量// @State finishTask:number = 0// @State stat:Stat = new Stat()@Provide stat:Stat = new Stat()// 任務列表@State tasks:Task[] = []build() {Row() {Column() {// 1、任務進度卡片TaskStatistics()// 2、使用任務列表子組件// TaskList({ totalTask:$totalTask, finishTask:$finishTask })TaskList()}.width('100%').height('100%').justifyContent(FlexAlign.Start)}.height('100%').width('100%').padding({top:20,bottom :20, left:10,right:10}).backgroundColor('#efefef')}}// 任務進度卡片子組件
@Component
struct TaskStatistics{/*@Prop finishTask:number@Prop totalTask:number*/@Consume stat:Statbuild(){Row(){Text('任務進度:').fontSize(22).fontWeight(FontWeight.Bold)Stack(){Progress({/*value : this.finishTask,total : this.totalTask,*/value : this.stat.finishTask,total : this.stat.totalTask,type : ProgressType.Ring})Row(){/*Text(this.finishTask.toString())Text(`/${this.totalTask.toString()}`)*/Text(this.stat.finishTask.toString())Text(`/${this.stat.totalTask.toString()}`)}}}.cardStyle().justifyContent(FlexAlign.SpaceEvenly)}
}// 新增任務與任務列表子組件
@Component
struct TaskList{// 總任務數量// @Link totalTask:number// 已完成任務數量// @Link finishTask:number// @Link stat:Stat@Consume stat:Stat// 任務列表@State tasks:Task[] = []handleTaskChange(){// 更新任務總數量// this.totalTask = this.tasks.lengththis.stat.totalTask = this.tasks.length// 更新已完成任務數量// this.finishTask = this.tasks.filter(item => item.finished).lengththis.stat.finishTask = this.tasks.filter(item => item.finished).length}build() {Column(){// 2、新增任務按鈕Button('新增任務').width(200).margin({top:20, bottom:20}).onClick(()=>{// 新增任務this.tasks.push(new Task())// 更新任務總數量// this.totalTask = this.tasks.lengththis.handleTaskChange()})// 3、任務列表展示List(){ForEach(this.tasks,(item:Task,index)=>{ListItem(){Row(){Text(item.name)Checkbox().select(item.finished).onChange(val => {// 更新任務狀態item.finished = val// 更新已完成任務數量// this.finishTask = this.tasks.filter(item => item.finished).lengththis.handleTaskChange()})}.cardStyle().height(60).margin({bottom:10}).justifyContent(FlexAlign.SpaceBetween)}.swipeAction({ end: this.deleteBtn(index)})})}.layoutWeight(1)}}@Builder deleteBtn(index){Button(){Image($r('app.media.icon_delete')).width(30).fillColor(Color.Red)}.width(40).height(40).type(ButtonType.Circle).backgroundColor(Color.Red).margin(6).onClick(() => {this.tasks.splice(index,1)this.handleTaskChange()})}
}

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

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

相關文章

【退役之重學Java】關于 Nacos 注冊中心

一、下載,安裝 見官網 二、配置 流程: 建module,pom,yml,主啟動,業務類 三、功能 負載均衡: Nacos 整合 Ribbon,可以使用 RestTemplate Nacos整合了Ribbon后,可以使用Res…

一個通過ADC采集NTC熱敏電阻的溫度傳感器

前言: 如何設計一個電路,使用具有逐次逼近寄存器(SAR)模數轉換器(ADC)的熱敏電阻直接監測溫度呢?溫度傳感電路需要使用負溫度系數(NTC)熱敏電阻與電阻器串聯形成分壓器,監測-25C至100C的溫度范圍。分壓器具有產生與監測的溫度成反比的輸出電壓的效果。電阻器分壓器的…

如何徹底搞懂迭代器(Iterator)設計模式?

說起迭代器(Iterator),相信你并不會陌生,因為我們幾乎每天都在使用JDK中自帶的各種迭代器。那么,這些迭代器是如何構建出來的呢?就需要用到了今天內容要介紹的迭代器設計模式。在日常開發過程中&#xff0c…

查找效率滿分的算法—— “二分查找” 算法 (Java版)

本篇會加入個人的所謂魚式瘋言 ??????魚式瘋言:??????此瘋言非彼瘋言 而是理解過并總結出來通俗易懂的大白話, 小編會盡可能的在每個概念后插入魚式瘋言,幫助大家理解的. 🤭🤭🤭可能說的不是那么嚴謹.但小編初心是能讓更多人…

removeAttribute和removeAttributeNode有什么區別(代碼舉例說明)

removeAttribute 和 removeAttributeNode 都是用于從 HTML 元素中移除屬性的 DOM 方法,但它們在用法和接受的參數上有一些區別。 removeAttribute removeAttribute 是一個元素(Element)對象的方法,它接受一個字符串參數&#xf…

深入了解Nginx(一):Nginx核心原理

一、Nginx核心原理 本節為大家介紹Nginx的核心原理,包含Reactor模型、Nginx的模塊化設計、Nginx的請求處理階段. (本文源自微博客,且已獲得授權) 1.1、Reactor模型 Nginx對高并發IO的處理使用了Reactor事件驅動模型。Reactor模型的基本組件包含時間收集…

華為OBS命令行簡單使用

華為OBS(Object Storage Service)是一種云存儲服務,提供了高可靠、高性能、安全的數據存儲能力。通過使用OBS的命令行工具obsutil,用戶可以方便地進行文件上傳、下載、刪除等操作,而無需依賴圖形界面。下面&#xff0c…

使用xsd驗證xml格式的正確性

1.1 基礎知識介紹 XML簡介:XML是可擴展標記語言(eXtensible Markup Language)的縮寫,它是一種數據表示格式,可以描述非常復雜的數據結構,常用于傳輸和存儲數據。xml文件、xml消息。XSD簡介:是X…

oracle 表同一列只取最新一條數據寫法

select * from (select t.*,row_number() over(partition by 去重列名 order by 排序列名 desc) as rnfrom 表名)where rn1 1.row_number() over(....): 為每條數據分配一個行號,1.2.3....這樣的 2.partition by : 以某列作為分組,每個分組行號從1開始&#xf…

ComputerLab實例2.0(繼承)

要求: Write a computer program that could be used to track users activities. Lab NumberComputer Station Numbers11-321-431-541-6 ? You run four computer labs. Each lab contains computer stations that are numbered as the above table. ? There…

LabVIEW和ZigBee無線溫濕度監測

LabVIEW和ZigBee無線溫濕度監測 隨著物聯網技術的迅速發展,溫濕度數據的遠程無線監測在農業大棚、倉庫和其他需環境控制的場所變得日益重要。開發了一種基于LabVIEW和ZigBee技術的多區域無線溫濕度監測系統。系統通過DHT11傳感器收集溫濕度數據,利用Zig…

uniapp-自定義navigationBar

封裝導航欄自定義組件 創建 nav-bar.vue <script setup>import {onReady} from dcloudio/uni-appimport {ref} from vue;const propsdefineProps([navBackgroundColor])const statusBarHeight ref()const navHeight ref()onReady(() > {uni.getSystemInfo({success…

圖生代碼,從Hello Onion 代碼開始

從Hello Onion 代碼開始 1&#xff0c;從代碼開始 原生語言采用java 作為載體。通過注解方式實現“UI可視化元素"與代碼bean之間的映射. 轉換示例 2&#xff0c;運行解析原理 在執行JAVA代碼期間&#xff0c;通過讀取注解信息&#xff0c;轉換為前端的JSON交由前端JS框…

NB49 牛群的秘密通信

描述 在一個遠離人類的世界中&#xff0c;有一群牛正在進行秘密通信。它們使用一種特殊的括號組合作為加密通信的形式。每一組加密信息均包括以下字符&#xff1a;(,{,[,),},]。 加密信息需要滿足以下有效性規則&#xff1a; 每個左括號必須使用相同類型的右括號閉合。左括號…

c++設計模式-->訪問者模式

#include <iostream> #include <string> #include <memory> using namespace std;class AbstractMember; // 前向聲明// 行為基類 class AbstractAction { public:virtual void maleDoing(AbstractMember* member) 0;virtual void femaleDoing(AbstractMemb…

OrangePiKunPengPro | 開發板學習與使用

OrangePi KunPengPro | 開發板學習與使用 時間:2024年5月23日20:51:12 文章目錄 `OrangePi KunPengPro` | 開發板學習與使用1.參考2.資料2.使用2-1.通過串口登錄系統2-2.通過SSH登錄系統2-3.安裝交叉編譯工具鏈2-4.復制文件到設備1.參考 1.OrangePi Kunpeng Pro Orange Pi官網…

c語言指針入門(二)

今天學習了指針的兩個常用場景&#xff0c;在此記錄&#xff0c;以便后續查看。 場景1&#xff1a;傳數組 在c語言中&#xff0c;我們在定義函數的時候是沒有辦法直接傳一個數組進去的&#xff0c;為了解決這個問題&#xff0c;我們一般將數組的名稱當作一個指針參數傳入到函數…

mysql主從復制的步驟和使用到的操作命令有哪些?

步驟&#xff1a; 配置主服務器&#xff08;Master&#xff09;&#xff1a; 啟用二進制日志記錄&#xff08;binary logging&#xff09;。配置主服務器的唯一標識&#xff08;server-id&#xff09;。創建用于復制的專用復制賬戶。 配置從服務器&#xff08;Slave&#xff0…

安裝Pnetcdf順便升級autoconf與automake

Netcdf NetCDF&#xff08;Network Common Data Form&#xff09;是一種用于存儲科學數據的文件格式和軟件庫。它是一種自描述、可移植且可擴展的數據格式&#xff0c;廣泛應用于氣象學、海洋學、地球科學和其他領域的科學研究。 NetCDF文件以二進制形式存儲&#xff0c;結構…

Qt | QGridLayout 類(網格布局)

01、上節回顧 Qt | QBoxLayout 及其子類(盒式布局)02、QGridLayout 簡介 1、網格布局原理(見下圖): 基本原理是把窗口劃分為若干個單元格,每個子部件被放置于一個或多個單元格之中,各 單元格的大小可由拉伸因子和一行或列中單元格的數量來確定,若子部件的大小(由 sizeH…