@Reusable-組件復用

@Reusable組件復用概述:

ArkUI布局中,將自定義組件從組件樹上移除后放入緩存池,后續在創建相同類型的組件節點時,直接復用緩存池中的組件對象。ArkUI中使用@Reusable裝飾器以實現自定義組件的復用。

常見的組件復用場景是當有大量數據使用相同的組件模版在界面中展示時,比如:List(列表)、Grid(網格)、Swiper(輪播)等組件中使用

優點:

1、避免頻繁創建和銷毀對象的過程,減少內存回收的頻率

2、復用緩存中的組件并直接綁定數據進行顯示,與創建新視圖相比,降低了計算開銷,提升了顯示效率

下面使用List列表加載大量數據的簡單案例:

1、用export class聲明在Item上呈現數據的ItemData類,并用@Observed修飾該類。

@Observed類裝飾器用于在涉及嵌套對象或數組的場景中進行雙向數據同步

@Observed
export class ItemData {id: string = '';title: string | Resource = '';content: string = '';from: string | Resource = '';isSelect:boolean = falseconstructor(id: string, type: number) {this.id = id;this.type = type;}
}

2、創建類ItemDataSource 并實現IDataSource接口,重寫IDataSource中的抽象函數:

IDataSource用于向ForEach或LazyForEach組件提供數據。

totalCount(): number-返回列表項展示總數

getData(index: number): any - 返回Item上展示的數據對象

registerDataChangeListener(listener: DataChangeListener): void - 注冊Data數據改變的監聽對象。

unregisterDataChangeListener(listener: DataChangeListener): void - 注銷Data數據改變的監聽對象

import { ItemData } from "./ItemData";
export class ItemDataSource implements IDataSource {private listeners: DataChangeListener[] = [];private originDataArray: ItemData[] = [];public totalCount(): number {return this.originDataArray.length;}public getData(index: number): ItemData {return this.originDataArray[index];}registerDataChangeListener(listener: DataChangeListener): void {console.log("listener----------",listener)if (this.listeners.indexOf(listener) < 0) {this.listeners.push(listener);}}unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {this.listeners.splice(pos, 1);}}

基于適配器(Adapter)設計模式,將數據源和視圖組件相互獨立,數據源的改變和組件的改變不相互影響。我們在ItemDataSource類中添加一下一些常見的更新數據的方法。

//更新所有列表數據
notifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded();});
}
//指定位置插入元素后更新
notifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index);});
}
//item數據源改變后更新
notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index);});
}
// 獲取數據后,更新列表
public pushArray(newData: ItemData[]): void {this.originDataArray.push(...newData);this.notifyDataReload();
}
... 增刪改查的方法雷同,不再贅述。

3、定義ListItemView組件,并且用@Reusable裝飾器修飾以實現組件的復用。

父子組件的傳參可以用@Require (@Prop、@Link ......)等裝飾器修飾

@Require裝飾器修飾的變量,在構造該自定義組件時,必須在構造時傳參。

@Prop裝飾的變量可以和父組件建立單向同步關系。

@Link裝飾的變量與其父組件中對應的數據源建立雙向數據綁定。

*子組件的點擊事件回調,可以聲明函數變量,

@Require onItemClick:(itemData:ItemData,index:number) => void = (itemData:ItemData,index:number)=>{},

import { ItemData } from "../../../model/ItemData";
@Reusable
@Component
export struct StudyListItemView {@Require @Prop mItemData:ItemData@Require @Prop index:number@Require onItemClick:(itemData:ItemData,index:number) => void = (itemData:ItemData,index:number)=>{}// update data in aboutToReuse methodaboutToReuse(params: Record<string, Object>): void {this.mItemData = params.mItemData as ItemData}isSelectIcon(isSelect:boolean):Resource{return isSelect? $r('app.media.ic_tab_lab_select'):$r('app.media.ic_tab_lab')}build() {Column() {Text(this.mItemData.title).fontSize(16).fontWeight(FontWeight.Medium).fontColor(Color.Black).lineHeight(22).textOverflow({ overflow: TextOverflow.Ellipsis }).width('100%')Row() {Text(this.mItemData.from).fontSize(12).fontWeight(FontWeight.Regular).fontColor(0x0A59F7)Text(this.mItemData.tail).fontSize(12).opacity(0.4).fontWeight(FontWeight.Regular).margin({ left: 6 }).layoutWeight(1)Image(this.isSelectIcon(this.mItemData.isSelect)).width(32).height(32)}.onClick((event)=>{this.onItemClick(this.mItemData,this.index)}).margin({ top: 12 })}.padding({top: 16,bottom: 12,left: 16,right: 16}).margin({ top: 12, left: 16, right: 16 }).borderRadius(12).backgroundColor(Color.White)}
}

4、使用List列表組件,渲染ListItemView組件

//創建ItemDataSource對象
private dataSource: ItemDataSource = new ItemDataSource();
aboutToAppear(): void {this.requestUpdate()
}
// 在鉤子函數中,模擬請求網絡數據
requestUpdate = () => {this.dataSource.pushArray(genMockItemData(1000));
}
// Item點擊是更改Item上的數據,通過數據驅動,改變ArkUI界面展示
onItemClick = (info:ItemData,index:number) =>{let tempInfo:ItemData = this.dataSource.getData(index)tempInfo.title = "--我是更改后的數據--"tempInfo.from = "update"tempInfo.tail = "13223211234"tempInfo.isSelect = !tempInfo.isSelectthis.dataSource.notifyDataChange(index)
}
//ArkUI 頁面繪制如下
build() {NavDestination(){RelativeContainer(){Column(){List(){LazyForEach(this.dataSource,(info:ItemData,index:number)=>{StudyListItemView({mItemData: info,index:index,onItemClick: this.onItemClick})},(item:StudyInfo)=>item.id)}.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]).cachedCount(1)}.height('100%')}.width('100%').height('100%')}.title("組件復用").onReady((context)=>{this.pathStack = context.pathStack}).backgroundColor(0xF1F3F5)
}

5、使用ArkUI的Refresh組件,實現列表組件的下拉刷新與上拉加載

@State isRefreshing: boolean = false; //是否正在刷新中

@State isLoading: boolean = false; //是否正在加載中

@State page: number = 1; //當前頁面

@State hasMoreData: boolean = true; // 無更多數據時展示視圖

Refresh(this.isRefreshing) {// List組件...// 加載更多提示項if (this.isLoading || this.hasMoreData) {ListItem() {Row() {if (this.isLoading) {LoadingProgress().color('#007DFF').width(24).height(24)}Text(this.isLoading ? '加載中...' : '上拉加載更多').fontSize(14).fontColor('#999999').margin({ left: 10 })}.width('100%').height(50).justifyContent(FlexAlign.Center)}} else {// 沒有更多數據提示ListItem() {Text('已經到底啦').fontSize(14).fontColor('#999999').width('100%').height(50).textAlign(TextAlign.Center)}}
}
.onRefresh(() => {this.onRefresh();
})

模擬下拉加載與上拉刷新視圖

// 下拉刷新處理函數
onRefresh = () => {this.isRefreshing = true;this.page = 1;setTimeout(()=>{this.requestUpdate();},1000)
}// 上拉加載處理函數
onReachBottom() {if (!this.isLoading && this.hasMoreData) {this.isLoading = true;this.page++;setTimeout(()=>{this.requestUpdate();},1000)}
}

模擬分頁請求網絡數據

requestUpdate() {this.isRefreshing = false;this.isLoading = false;let  tempData = getMockItemDataByPage(this.page, this.page == 4 ? 10 : 8)if (tempData.length < 10){this.hasMoreData = true}else{this.hasMoreData = false}if (this.page == 1) {this.dataSource.resetArray(tempData);}else {this.dataSource.pushArray(tempData);}
}

至此List列表分頁加載網絡數據并完成組件復用。@Component組件完整代碼如下:

@Component
export struct StudyList{private pathStack:NavPathStack = new NavPathStack()private dataSource: ItemDataSource = new ItemDataSource();@State isRefreshing: boolean = false;@State isLoading: boolean = false;@State page: number = 1;@State hasMoreData: boolean = true;aboutToAppear(): void {this.requestUpdate()}// 下拉刷新處理函數onRefresh = () => {this.isRefreshing = true;this.page = 1;setTimeout(()=>{this.requestUpdate();},1000)}// 上拉加載處理函數onReachBottom() {if (!this.isLoading && this.hasMoreData) {this.isLoading = true;this.page++;setTimeout(()=>{this.requestUpdate();},1000)}}requestUpdate() {this.isRefreshing = false;this.isLoading = false;let  tempData = getMockItemDataByPage(this.page, this.page == 4 ? 10 : 8)if (tempData.length < 10){this.hasMoreData = true}else{this.hasMoreData = false}if (this.page == 1) {this.dataSource.resetArray(tempData);}else {this.dataSource.pushArray(tempData);}}onItemClick = (info:ItemData,index:number) =>{let tempInfo:ItemData = this.dataSource.getData(index)tempInfo.title = "--我是更改后的數據--"tempInfo.from = "update"tempInfo.tail = "1分鐘之前"tempInfo.isSelect = !tempInfo.isSelectthis.dataSource.notifyDataChange(index)}build() {NavDestination(){RelativeContainer(){Column(){Refresh({ refreshing: this.isRefreshing }){List(){LazyForEach(this.dataSource,(info:ItemData,index:number)=>{StudyListItemView({mItemData: info,index:index,onItemClick: this.onItemClick})},(item:StudyInfo)=>item.id)// 加載更多提示項if (this.isLoading || this.hasMoreData) {ListItem() {Row() {if (this.isLoading) {LoadingProgress().color('#007DFF').width(24).height(24)}Text(this.isLoading ? '加載中...' : '上拉加載更多').fontSize(14).fontColor('#999999').margin({ left: 10 })}.width('100%').height(50).justifyContent(FlexAlign.Center)}} else {// 沒有更多數據提示ListItem() {Text('已經到底啦').fontSize(14).fontColor('#999999').width('100%').height(50).textAlign(TextAlign.Center)}}}.width('100%').height('100%').onReachEnd(() => {this.onReachBottom();}).expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM]).cachedCount(1)}.onRefreshing(()=>{this.onRefresh()})}.height('100%')}.width('100%').height('100%')}.title("組件復用").onReady((context)=>{this.pathStack = context.pathStack}).backgroundColor(0xF1F3F5)}
}

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

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

相關文章

黑馬點評系列問題之p63unlock.lua不知道怎么整

問題描述&#xff1a;這個位置的這個unlock.lua文件是怎么生成的。老師給的不是很清楚。解決右鍵單擊resources。如圖輸入回車&#xff0c;然后界面的上方&#xff0c;大概是在這個位置&#xff0c;會有讓你引入這個依賴的選項&#xff0c;我的已經沒有了。他會出來大概三個選項…

Python爬蟲實戰:研究Python-Markdown庫相關技術

1. 引言 在當今信息爆炸的時代,網絡上存在著大量有價值的技術文章。對于技術人員來說,如何高效地收集、整理和保存這些文章是一個重要的問題。爬蟲技術可以幫助我們自動從網絡上獲取所需的文章內容,而 Markdown 作為一種輕量級標記語言,因其簡潔的語法和良好的兼容性,成為…

JAVA經典單例模式

前言單例模式&#xff08;Singleton Pattern&#xff09;是一種創建型設計模式&#xff0c;確保一個類僅有一個實例&#xff0c;并提供全局訪問點。它在需要控制資源&#xff08;如數據庫連接、配置管理&#xff09;或避免重復創建對象的場景中廣泛應用。一&#xff0c;核心概念…

20250715問答課題-基于BERT與混合檢索問答系統

1. 引言構建一個基于BERT與混合檢索策略的智能問答系統&#xff0c;通過深度學習與傳統檢索技術的融合&#xff0c;解決了心法領域知識檢索中的三個關鍵問題&#xff1a;(1)專業術語的語義理解不足&#xff1b;(2)問答匹配精度低&#xff1b;(3)檢索結果多樣性差。2. 方法2.1. …

面向對象與面向過程、函數式編程

面向對象與面向過程、函數式編程 1. 面向過程編程&#xff08;Procedure-Oriented Programming&#xff09; 面向過程編程將程序視為一系列函數的集合&#xff0c;數據和操作數據的函數是分離的。在 Vue 3 中&#xff0c;這種風格通常表現為使用組合式 API&#xff08;Composit…

基于大數據的淘寶用戶行為數據分析系統的設計與實現

開發環境開發語言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服務器&#xff1a;tomcat7 數據庫&#xff1a;mysql5.7&#xff08;一定要5.7版本&#xff09; 數據庫工具&#xff1a;Navicat11 開發軟件&#xff1a;eclipse/myeclipse/idea Maven…

視頻人臉處理——人臉面部動作提取

文章目錄基于openface實現的技術方案windows環境下使用1. 安裝依賴軟件2. 下載OpenFace代碼3. 編譯OpenFace4. 提取面部動作單元5.選擇提取目標方案liunx環境下使用安裝與配置使用 OpenFace 提取面部動作單元應用場景基于py-feat實現的方案1. 從HuggingFace下載模型并設置Detec…

【Docker基礎】Dockerfile構建與運行流程完全指南:從原理到實踐優化

目錄 引言 1 docker build命令參數詳解 1.1 命令概述 1.2 常用參數詳解 1.2.1 -t, --tag 1.2.2 -f, --file 1.2.3 --build-arg 1.2.4 --no-cache 1.2.5 --pull 1.3 構建流程圖解 2 構建上下文&#xff08;Context&#xff09;優化技巧 2.1 構建上下文定義 2.2 優化…

StarRocks Community Monthly Newsletter (Jun)

版本動態 v3.5.0 存算分離&#xff1a;支持生成列、主鍵表重建索引&#xff1b;大規模導入邏輯優化&#xff0c;降低小文件數量。 數據湖分析&#xff1a;Beta 支持 Iceberg 視圖創建與修改&#xff1b;支持 Iceberg REST Catalog 嵌套命名空間&#xff1b; 性能提升與查詢優…

HDMI接口 vs. DisplayPort接口:電競玩家該如何選擇更優?

在搭建游戲主機或電競PC時&#xff0c;顯示器接口的選擇&#xff08;HDMI vs. DP&#xff09;會直接影響畫質、刷新率和延遲表現。本文將從分辨率、刷新率、可變刷新率&#xff08;VRR&#xff09;、帶寬、兼容性等角度對比&#xff0c;幫你選出最適合游戲的接口。1. 基礎對比&…

論文筆記:Learning Cache Replacement with CACHEUS

2021 USENIX GitHub - sylab/cacheus: The design and algorithms used in Cacheus are described in this USENIX FAST21 paper and talk video: https://www.usenix.org/conference/fast21/presentation/rodriguez Learning Cache Replacement with CACHEUS 1 intro 基于…

極致cms多語言建站|設置主站默認語言與設置后臺固定語言為中文

小記 很長時間沒有建站了,最近有需求所以又回爐了&#xff0c;使用的極致cms 極致cms幫助文檔 | 極致CMS幫助文檔 由于很長時間沒做&#xff0c;又遇到了之前碰到的兩個問題&#xff0c;憑借經驗和記憶還是處理掉了 1.當網站前臺使用?len或?lzh來切換語言時&#xff0c;管…

Linux Vim 編輯器詳解:從入門到進階(含圖示+插件推薦)

前言在 Linux 的世界中&#xff0c;Vim 是一款被無數開發者喜愛和追捧的強大文本編輯器。如果你厭倦了鼠標點來點去&#xff0c;不妨試試 Vim —— 一款專注于高效鍵盤操作的“終極利器”。本文將帶你全面了解 Vim 的基本概念、模式切換、常用命令、窗口管理&#xff0c;并附上…

web前端渡一大師課 01 事件循環

一. 瀏覽器的進程模型 1.何為進程?程序運行需要有它自己專屬的內存空間,可以把這塊內存空間簡單理解為進程 每個應用至少有一個進程,進程之間相互獨立,即使要通信,也需要雙方同意 2.何為線程?有了進程后,就可以運行程序的代碼了,運行代碼的"人",稱之為"線程&…

linux網絡存儲——freeNAS的安裝配置

一、前言 freeNAS 是一款基于 FreeBSD 的開源網絡存儲操作系統&#xff0c;支持文件共享&#xff08;如 SMB/CIFS、NFS、AFP&#xff09;、數據備份、虛擬化存儲等功能。同時FreeNAS開源優勢明顯&#xff0c;代碼開放可自主定制&#xff0c;能滿足多樣需求。支持多種協議…

深度學習圖像分類數據集—七種樹葉識別分類

該數據集為圖像分類數據集&#xff0c;適用于ResNet、VGG等卷積神經網絡&#xff0c;SENet、CBAM等注意力機制相關算法&#xff0c;Vision Transformer等Transformer相關算法。 數據集信息介紹&#xff1a;七種樹葉識別分類&#xff1a;[冬青葉, 楊樹葉, 柳葉, 梧桐葉, 石楠葉,…

c++圖形題練習程序

一.練習題背景 這題是作者再一家公司實習的時候&#xff0c;實習期間的一個考核題目&#xff0c;感覺還是比較有價值的。希望能給還在努力的學弟學妹們一些啟發。 題目大致就是要求用繼承和多態來實現圓、三角形和長方形的面積和周長求解。這步的大致思路是這樣的&#xff0c;你…

【論文閱讀 | PR 2024 |ITFuse:一種用于紅外與可見光圖像融合的交互式 Transformer】

論文閱讀 | PR 2024 |ITFuse&#xff1a;一種用于紅外與可見光圖像融合的交互式 Transformer1.摘要&&引言2.方法2.1 問題表述2.2 框架概述2.3 特征交互模塊2.3.1 共同特征提取分支&#xff08;IcI_{c}Ic? 分支&#xff09;2.3.2 獨特特征提取分支&#xff08;I1I_{1}I…

【Qt】 設計模式

在Qt應用程序開發中&#xff0c;結合數據庫操作、通信、界面邏輯和顯示等功能&#xff0c;以下是常用的設計模式及其典型應用場景&#xff1a; 一、MVC/MVVM&#xff08;模型-視圖-控制器/視圖模型&#xff09; 作用&#xff1a;分離數據&#xff08;模型&#xff09;、界面&am…

【HarmonyOS】ArkUI-X 跨平臺框架入門詳解(一)

【HarmonyOS】ArkUI-X 跨平臺框架入門詳解&#xff08;一&#xff09; 一、前言 1、ArkUI-X框架是什么&#xff1f; ArkUI-X是在ArkUI開發框架的基礎上&#xff0c;進行擴展。支持多個OS平臺&#xff0c;目前支持OpenHarmony、HarmonyOS、Android、 iOS。2、ArkUI-X目前的能力現…