当前位置: 首页 > news >正文

seo网站诊断价格已备案网站域名网

seo网站诊断价格,已备案网站域名网,购物网页设计模板html,WordPress老文章提示在 ArkTS 的开发中,如果你要渲染一个很长的列表,比如商品列表、评论列表或者朋友圈动态,用传统的循环结构(比如 ForEach)很容易导致性能问题,尤其是加载慢、卡顿甚至内存暴涨。 这时候就要用到 懒加载渲染组…

在 ArkTS 的开发中,如果你要渲染一个很长的列表,比如商品列表、评论列表或者朋友圈动态,用传统的循环结构(比如 ForEach)很容易导致性能问题,尤其是加载慢、卡顿甚至内存暴涨。

这时候就要用到 懒加载渲染组件——LazyForEach

LazyForEach 是 ArkTS 提供的一种 延迟渲染列表项的方式。只有当列表项真正要被显示在屏幕上时,相关组件才会被创建和渲染,从而节省内存和提升性能。

可以把它理解成 ArkTS 中的“虚拟滚动列表”。

LazyForEach的使用限制

  • LazyForEach必须在容器组件内使用仅有List、Grid、Swiper以及WaterFlow组件支持数据懒加载(可配置cachedCount属性,即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据。支持数据懒加载的父组件根据自身及子组件的高度或宽度计算可视区域内需布局的子节点数量,高度或宽度的缺失会导致部分场景懒加载失效

catchdCount

List设置cachedCount后,显示区域外上下各会预加载并布局cachedCount行ListItem。

  • LazyForEach依赖生成的键值判断是否刷新子组件,键值不变则不触发刷新。
  • 容器组件内只能包含一个LazyForEach。以List为例,不推荐同时包含ListItem、ForEach、LazyForEach。也不推荐同时包含多个LazyForEach。
  • LazyForEach在每次迭代中,必须创建且只允许创建一个子组件;即LazyForEach的子组件生成函数有且只有一个根组件
  • 生成的子组件必须是允许包含在LazyForEach父容器组件中的子组件。
  • 允许LazyForEach包含在if/else条件渲染语句中,也允许LazyForEach中出现if/else条件渲染语句。
  • 键值生成器必须针对每个数据生成唯一的值,如果键值相同,将导致键值相同的UI组件渲染出现问题。
  • LazyForEach必须使用DataChangeListener对象进行更新。重新赋值第一个参数dataSource会导致异常;dataSource使用状态变量时,状态变量改变不会触发LazyForEach的UI刷新
  • 为了高性能渲染,使用DataChangeListener对象的onDataChange方法更新UI时,需要生成不同于原来的键值来触发组件刷新。

LazyForEach键值生成规则

LazyForEach提供了参数keyGenerator,开发者可以使用该函数生成自定义键值。如果未定义keyGenerator函数,ArkUI框架将使用默认的键值生成函数:(item: Object, index: number) => { return viewId + ‘-’ + index.toString(); }。viewId在编译器转换过程中生成,同一个LazyForEach组件内的viewId一致。

基本语法

LazyForEach(dataSource: IDataSource,             // 需要进行数据迭代的数据源itemGenerator: (item: any, index?: number) => void,  // 子组件生成函数keyGenerator?: (item: any, index?: number) => string // 键值生成函数
): void
  • dataSource:IDataSource

    LazyForEach数据源,需要开发者实现相关接口

  • itemGenerator:(item: any, index: number) => void

    子组件生成函数,为数组中的每一个数据项创建一个子组件。

  • keyGenerator: (item: any, index: number) => string

    键值生成函数,用于给数据源中的每一个数据项生成唯一且固定的键值。修改数据源中的一个数据项若不影响其生成的键值,则对应组件不会被更新,否则此处组件就会被重建更新。keyGenerator参数是可选的,但是,为了使开发框架能够更好地识别数组更改并正确更新组件,建议提供

实现IDataSource接口

interface IDataSource {totalCount(): number; // 获得数据总数getData(index: number): Object; // 获取索引值对应的数据registerDataChangeListener(listener: DataChangeListener): void; // 注册数据改变的监听器unregisterDataChangeListener(listener: DataChangeListener): void; // 注销数据改变的监听器
}

DataChangeListener接口

interface DataChangeListener {onDataReloaded(): void; // 重新加载数据完成后调用onDataAdded(index: number): void; // 添加数据完成后调用onDataMoved(from: number, to: number): void; // 数据移动起始位置与数据移动目标位置交换完成后调用onDataDeleted(index: number): void; // 删除数据完成后调用onDataChanged(index: number): void; // 改变数据完成后调用onDataAdd(index: number): void; // 添加数据完成后调用onDataMove(from: number, to: number): void; // 数据移动起始位置与数据移动目标位置交换完成后调用onDataDelete(index: number): void; // 删除数据完成后调用onDataChange(index: number): void; // 改变数据完成后调用
}

创建LazyForEach

首次渲染

在LazyForEach首次渲染时,会根据上述键值生成规则为数据源的每个数组项生成唯一键值并创建相应的组件。

局部代码如下:

class MyDataSource extends BasicDataSource {private dataArray: string[] = [];public totalCount(): number {return this.dataArray.length;}public getData(index: number): string {return this.dataArray[index];}public pushData(data: string): void {this.dataArray.push(data);this.notifyDataAdd(this.dataArray.length - 1);}
}@Entry
@Component
struct MyComponent {private data: MyDataSource = new MyDataSource();aboutToAppear() {for (let i = 0; i <= 20; i++) {this.data.pushData(`Hello ${i}`);}}build() {List({ space: 3 }) { // 必须在容器组件内LazyForEach(this.data, (item: string) => {ListItem() {Row() {Text(item).fontSize(50).onAppear(() => {console.info(`appear: ${item}`);})}.margin({ left: 10, right: 10 })}}, (item: string) => item) // 生成唯一键值}.cachedCount(5) // 设置显示区域外上下预加载布局}
}

渲染结果如图

在这里插入图片描述

非首次渲染

当LazyForEach数据源发生变化,需要再次渲染时,开发者应根据数据源的变化情况调用listener对应的接口,通知LazyForEach做相应的更新。

局部代码如下:

class MyDataSource extends BasicDataSource {private dataArray: string[] = [];public totalCount(): number {return this.dataArray.length;}public getData(index: number): string {return this.dataArray[index];}public pushData(data: string): void {this.dataArray.push(data);this.notifyDataAdd(this.dataArray.length - 1);}
}@Entry
@Component
struct MyComponent {private data: MyDataSource = new MyDataSource();aboutToAppear() {for (let i = 0; i <= 20; i++) {this.data.pushData(`Hello ${i}`);}}build() {List({ space: 3 }) {LazyForEach(this.data, (item: string) => {ListItem() {Row() {Text(item).fontSize(50).onAppear(() => {console.info(`appear: ${item}`);})}.margin({ left: 10, right: 10 })}.onClick(() => {// 点击追加子组件this.data.pushData(`Hello ${this.data.totalCount()}`);})}, (item: string) => item)}.cachedCount(5)}
}

渲染结果如图:
在这里插入图片描述

LazyForEach之前:先实现IDataSource接口

// 实现IDataSource接口,用于管理listener监听,以及通知LazyForEach数据更新
class BasicDataSource implements IDataSource {private listeners: DataChangeListener[] = [];private originDataArray: string[] = [];public totalCount(): number {return this.originDataArray.length;}public getData(index: number): string {return this.originDataArray[index];}// 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听registerDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {console.info('add listener');this.listeners.push(listener);}}// 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {console.info('remove listener');this.listeners.splice(pos, 1);}}// 通知LazyForEach组件需要重载所有子组件notifyDataReload(): void {this.listeners.forEach(listener => {listener.onDataReloaded();});}// 通知LazyForEach组件需要在index对应索引处添加子组件notifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDataAdd(index);// 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);});}// 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index);// 写法2:listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);});}// 通知LazyForEach组件需要在index对应索引处删除该子组件notifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDataDelete(index);// 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);});}// 通知LazyForEach组件将from索引和to索引处的子组件进行交换notifyDataMove(from: number, to: number): void {this.listeners.forEach(listener => {listener.onDataMove(from, to);// 写法2:listener.onDatasetChange(//         [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);});}notifyDatasetChange(operations: DataOperation[]): void {this.listeners.forEach(listener => {listener.onDatasetChange(operations);});}
}
http://www.dtcms.com/a/567470.html

相关文章:

  • 云南省建设厅定额网站宁波建设安全协会网站
  • 地下城做解封任务的网站纺织行业网站怎么做吸引人
  • 建设网站的价格表注册了域名怎么添加到自己的网站
  • 河北品牌网站建设网站建设 视频教程
  • seo网站改版方案怎么写怎么分析网站用什么技术做的
  • wordpress 电商网站济南企业免费建站
  • 广告设计公司宁波百度seo排名优化软件
  • 国外购买域名网站电商营销推广方案
  • 建设网站服务域名可以自己注册吗
  • 石河子做网站公司贵州软件定制
  • 武进附近做网站的公司有哪些如何进行企业营销型网站建设
  • 一级a做爰片 网站就能看网站体系优势
  • 湖北襄阳网站建设企业网页制作哪个公司好
  • 常用外贸网站wordpress比较好的主题
  • 贵州省建设厅官网网站wordpress error log
  • 江阴网站建设培训国际外贸平台排名
  • 泉州网站建设dreamnm做的好的宠物食品网站
  • 怎样做视频上网站赚钱软文发稿平台
  • wordpress双站电子产品网站建设策划
  • 阿里巴巴网站制作内网穿透做网站
  • 顺义企业网站建站公司北京网站搭建服务
  • 温州建设网站哪家好建网站不花钱免费建站
  • 福建省建设干部培训中心网站首页网站空间500m是什么
  • wex5 后端实现全网站开发北京市通信管理局 网站备案
  • 小说网站开发源码东营房地产网站建设
  • 中国建设会计学网站自学网站查分数
  • 高校门户网站建设建议视频网站dedecms
  • 西安网站建设 大德织梦网站logo
  • 微信平台APP网站建设怎么样wordpress的模板目录在哪里
  • 焦作网站开发重庆做网站 外包公司