@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目前的能力现…