一行代码解决Taro中VirtualList虚拟列表渲染抖动的问题

news2024/11/23 11:08:42

文章目录

      • 引言:问题背景
      • 一、虚拟列表的使用场景
      • 二、解决Taro组件VirtualList的抖动问题
        • 1. VirtualList的使用方法
        • 2. 解决之法
      • 三、扩展场景:关于key的其他抖动问题,如表格组件

引言:问题背景

使用Taro 提供的组件库 VirtualList 时,数据源长度改变后,发生渲染抖动。

需求的普遍场景是上百条甚至上千条数据,因此我们采用了虚拟列表。然而,也有例外情况,即虚拟列表的数据源长度变为了个位数,比如原来是 8 条,改变筛选条件后,结果为 5 条数据,此时出现了渲染抖动。

现象:
改变筛选条件后,列表由原来的 8 条从下到上 缓慢 减为了 5 条,下面的数据逐渐消失而不是直接消失(消失动态数据,如state——>留下静态数据——>全部消失),存在一个渲染抖动的过程。

这种情况在数据量大时未发现。

那么本篇内容就对解决渲染抖动的过程进行记录和分享,希望可以帮助到你。

一、虚拟列表的使用场景

首先,我们来熟悉一下使用虚拟列表(Virtual List)的场景。它是一种优化长列表性能的技术,适用于以下场景:

  1. 长列表:当列表中的项非常多时,例如几百甚至几千个,虚拟列表可以提高性能并减少内存占用。
  2. 可滚动列表:当列表需要支持滚动时,虚拟列表可以提供平滑的滚动体验,无论列表有多长。
  3. 复杂列表项:当列表项比较复杂,包含大量的子组件、图片或其他复杂的渲染逻辑时,虚拟列表可以减少不必要的渲染开销。

其次,我们再来了解一下它的其他知识:

  • 虚拟列表的工作原理是只渲染当前可见区域内的列表项,而不是一次性渲染所有的列表项。通过动态加载和卸载列表项,虚拟列表可以显著提高性能和响应速度。
  • 在使用虚拟列表时,需要指定列表的高度(或宽度)和每个列表项的高度(或宽度)。虚拟列表会根据可见区域的大小和滚动位置计算出当前需要渲染的列表项,并在滚动时动态更新渲染的内容。
  • 虚拟列表通常与滚动容器(如ScrollView)结合使用,以实现滚动功能。它可以在Web开发中使用,也可以在跨平台开发框架(如Taro、React Native等)中使用。
  • 虚拟列表的数据常来源于远程加载。

总之,虚拟列表就是只渲染当前可视区域(visible viewport) 的视图,非可视区域的视图在用户滚动到可视区域再渲染:
虚拟列表样例

二、解决Taro组件VirtualList的抖动问题

1. VirtualList的使用方法

项目中,如果我们引用了Taro,那么正常是这样写的:

// ...
import VirtualList from "@tarojs/components/virtual-list";

export default class Index extends Component {
  state = {
    data: [],
  }
  function buildData() {
    // 接口请求列表数据
  }
  // 列表单项组件
  const Row = React.memo(({ id, index, data }) => {
    // odd 奇数,even:偶数
    return (
      <View id={id} className={index % 2 ? 'ListItemOdd' : 'ListItemEven'}>
        Row {index} : {data[index]}
      </View>
    )
  })

  render() {
    const { data } = this.state;
    const dataLen = data.length;
    return (
      <VirtualList
        height={800} /* 列表的高度 */
        width="100%" /* 列表的宽度 */
        item={Row} /* 列表单项组件,这里只能传入一个组件 */
        itemData={data} /* 渲染列表的数据 */
        itemCount={dataLen} /* 渲染列表的长度 */
        itemSize={100} /* 列表单项的高度  */
      />
    )
  }
}

部分参数说明:

item: ReactComponent (原 children 参数)
将要渲染的列表单项组件。组件的 props 有 4 个属性:

  • id: 单项的 ID,必须传入组件的 id 中
  • index: 组件渲染数据的索引
  • data: 组件渲染的数据,同虚拟列表 itemData
  • isScrolling: 组件是否正在滚动,当 useIsScrolling 值为 true 时返回布尔值,否则返回 undefined

推荐使用 React.memo 或 React.PureComponent 或使用 shouldComponentUpdate() 来优化此组件,避免不必要的渲染。

上述代码参考 Taro官方文档,博主有二次编辑、加注释,方便更好的理解。

2. 解决之法

若是参考官方文档,它并未提到 key
熟悉React的同学会知道,key 是一个 ReactElement 的基本属性,它的作用是保证组件的唯一性,提高渲染性能(这一点如果不清楚的话评论区可以提问)。

常见案例:如果在数组 map 中,我们经常会给渲染组件加一个key。

那么,博主也是又看官网的,又搜百度的,没找到答案。后面在openAI的提示下,才有了加key的方案,它是这么说的:

  • 可能是因为Taro的VirtualList组件在数据源长度变化时,没有立即更新渲染的列表项,而是在下一次渲染时才更新,这就导致了抖动的问题。
  • 为了解决这个问题,你可以尝试在数据源长度变化时,强制VirtualList组件立即重新渲染。你可以通过在VirtualList组件的key属性上设置一个与数据源长度相关的值来实现这个目标。当数据源长度变化时,key属性的值也会变化,这会导致VirtualList组件立即重新渲染。

修改原代码:

<VirtualList
   key={data.length} // 添加这一行
   height={800} /* 列表的高度 */
   width="100%" /* 列表的宽度 */
   item={Row} /* 列表单项组件,这里只能传入一个组件 */
   itemData={data} /* 渲染列表的数据 */
   itemCount={dataLen} /* 渲染列表的长度 */
   itemSize={100} /* 列表单项的高度  */
/>

核心即加 key,一行代码解决: key={data.length} ,再次运行项目就没有之前的问题啦!

三、扩展场景:关于key的其他抖动问题,如表格组件

我们在开发项目时,特别是后台管理系统中,表格组件Table使用的格外广泛。
比如 ant design组件库,

import React from 'react'; 
// ...
// render中
<Table columns={columns} pagination={pagination} dataSource={data} />

有时可能遇到表格渲染抖动或错误的现象。例如:更改筛选条件/切换页面,表格会带出先前的行记录;或行记录重复。遇到这些问题,我们首先会去看服务端接口返回是否正常,一看:“接口返回没问题啊!这咋回事啊???”,然后又去看自己的前端代码……

之前博主遇到的时候,心里也是大大的问号,各处排查,最后发现是 rowKey 不唯一导致的渲染出错

解决:Table加个属性:rowKey='recordId'rowKey={(record)=>record.id} ,OK,刷新项目,乱象消失。

关于rowKey的说明:

rowKey表格行 key 的取值,可以是字符串或一个函数string 或function(record): string

Antd官方是这么说的:
按照 React 的规范,所有的数组组件必须绑定 key。在 Table 中,dataSourcecolumns 里的数据值都需要指定 key 值。对于 dataSource 默认将每列数据的 key 属性作为唯一的标识。

点开看大图:

image.png
无论是哪个组件库或框架,VUE也好,React 也好,数组的 key 是非常必要的!

读完本篇文章,你可以获得:

  • 虚拟列表概念
  • 虚拟列表的使用场景
  • 性能优化策略-key
  • 虚拟列表渲染抖动的问题解决
  • 表格抖动或渲染错误的解决方向

希望能帮助到你,如有收获可点赞收藏哦。
如有疑问请评论区提出,欢迎沟通👏🏻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/772891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信合并转发的图片如何批量保存

今天遇到一个场景&#xff1a;朋友给转发来了一个合并的聊天记录&#xff0c;里面是几十张图片&#xff0c;希望能打印出来。逐张保存太费手了。下面是批量保存图片的方法&#xff1a; 1、登录PC端微信&#xff1b; 2、将要保存图片的这条合并转发的聊天记录收藏&#xff1b;…

内存参数问题导致内存溢出

问题&#xff1a;内存参数问题导致内存溢出 1、文件过大&#xff0c;进行分块 2、 运行参数&#xff0c;使用最大内存配置2时&#xff0c;导致空指针异常。 3、获取详细报错信息-内存溢出 多线程捕获Throwable异常 修改代码&#xff0c;捕获Throwable&#xff0c;获取异常 异…

Go安装环境

一、golang编译器下载 网址&#xff1a;https://golang.google.cn/dl/ 我自己是在本地测试的 就安装的是windows的 二、环境配置 编译器安装完成后&#xff0c;找到安装文件夹下的bin文件夹&#xff0c;里面含有 go.exe 可执行文件&#xff0c;将 bin 文件夹的路径添加到系统…

图像标注是什么?及其类型和应用

什么是图像标注&#xff1f; 图像标注是与您交互的许多人工智能产品的基础&#xff0c;并且是计算机视觉&#xff08;CV&#xff09;领域重要的过程之一。在图像标注过程中&#xff0c;数据标注员使用标签或元数据来标记AI模型学习识别的数据特征。然后&#xff0c;这些图像标…

C++模拟实现vector

目录 1.代码实现 2.注意事项 1.成员变量 2. 不能使用memcpy函数拷贝数据 1.用string类型测试时&#xff0c;要考虑到vs可能把数据存储在数组buffer里面 3.insert函数中指针的失效性 1.加引用&#xff0c;那么就不能传常量&#xff0c;比如v.begin() 3 2.加引用&#x…

C#委托相关知识

最开始学习C#的时候&#xff0c;简单的看过委托&#xff0c;最近工作中经常需要使用到委托。这篇笔记是对之前看过的委托的一个补充&#xff0c;也是对最近工作中遇到的委托的一个总结吧。 这里使用的是窗体程序作为例子。实例在文末&#xff0c;可下载。 委托是一个类&#xf…

【动手学深度学习】--15.含并行连结的网络GoogLeNet

文章目录 含并行连结的网络GoogLeNet1.Inception块2.GoogLeNet模型3.训练模型 含并行连结的网络GoogLeNet 学习视频&#xff1a;含并行连结的网络 GoogLeNet / Inception V3【动手学深度学习v2】 官方笔记&#xff1a;含并行连结的网络&#xff08;GoogLeNet&#xff09; 1.…

【智能交互】OPPO接入小布语音技能通关教程:个人开发者实现接口调用

目录 前言实际操作注册OPPO平台账号打开创建技能界面创建技能创建意图槽位解析对话管理对话测试接口代码编写接口创建新建意图对话管理测试猜想测试相关文档前言 适用人群:本教程适合大赛接入小布语音技能的同学以及初次使用小布助手的开发者 本篇文章是博主弄了多次测试才勉…

勒索花样繁多,“Sophos Encrypt”披马甲进行勒索攻击

近日&#xff0c;网络安全供应商Sophos发表声明&#xff0c;称Sophos被一款名为“Sophos Encrypt”新型勒索软件冒充&#xff0c;该勒索软件进行攻击时会冒用Sophos品牌名称&#xff0c;并将用户重要文件进行加密以勒索赎金。 现在的勒索软件类型多样&#xff0c;令企业防不胜防…

LeetCode·每日一题·874. 模拟行走机器人·哈希

作者&#xff1a;小迅 链接&#xff1a;https://leetcode.cn/problems/walking-robot-simulation/solutions/2350184/ha-xi-biao-zhu-shi-chao-ji-xiang-xi-by-x-20cg/ 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 著作权归作者所有。商业转载请联系作者获得授权&am…

【iPaaS干货分享】大型企业都在用的新一代SAP集成方式,你了解吗?

目录 目前企业实现SAP集成的主要方式 一、使用SAP PI/PO实现SAP与外部系统的集成 二、使用自开发方式 SAP新一代集成方式——基于iPaaS SAP连接器 一、分钟级实现SAP系统的集成 二、统一集成接口及安全管理 三、可视化编排改造SAP接口 SAP&#xff08;Systems, Applicatio…

GO语言方法集

实际上,这里 那为什么还要生产包装方法呢?主要是为了支持接口. 接口不能直接使用接收者为值类型的方法.因为我们A(a)接受者是第一个参数,而这个参数是动态派发的,参数放在栈的局部变量,编译器在编译阶段不能确定这个量的大小.而指针平台确定了大小也就确定了.面对这个问题,编译…

如何使用MATLAB软件完成生态碳汇涡度相关监测与通量数据分析

MATLAB MATLAB是美国MathWorks公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 [1] MATLAB是matrix&laboratory两个词的组合&#xff0c;意为矩阵工厂&a…

Java List集合 -- 最常用的两种排序方法

现在有一个类 public class Person {private int id;private int age;private String name;public Person(int id, int age, String name) {this.id id;this.age age;this.name name;}public int getId() {return id;}public int getAge() {return age;}public String getN…

149206-86-0,DOTA GGGA,双功能螯合物,修饰在多肽上的螯合剂

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 规格单位&#xff1a;g |货期&#xff1a;按照具体的库存进行提供 | 纯度&#xff1a;95%| PART1-------试剂描述&#xff1a; 螯合剂Dota-ggga&#xff08;CAS号&#xff1a;149206-86-0&#xff09;&#xff0c;螯合…

skbuff.h在哪

今天看来下底层socket的实现&#xff0c;发现很多人都说有个skbuff结构&#xff0c;我就想着去找下这个&#xff0c; cat /include/linux/skbuff.h 结果找不到&#xff0c;查了下&#xff0c;需要下载内核源码 //Ubuntusudo apt install linux-headers-genericdpkg -S skbuff.…

Linux系统配置Node.js环境详细教程(图文讲解)

前言&#xff1a;在使用Jenkins部署Vue项目的时候&#xff0c;如果没有安装Node.js环境的话&#xff0c;Jenkins会无法对Vue项目进行构建&#xff0c;所以本期出了一篇关于在Linux系统如何配置Node.js环境的讲解&#xff0c;以博客的方式记录一下我详细的配置流程和踩过的坑&am…

包的使用及其创建

文章目录 前言类名冲突完整的类路径创建包导入类包总结 前言 java语言中&#xff0c;包在整个管理过程中发挥了重要的作用。使用包&#xff0c;可以有效地管理繁多的类文件&#xff0c;解决了类名重复的问题。在类中应用包和权限修饰符&#xff0c;可以控制他人对类成员的方法的…

旅游卡系统加盟代理软件开发

旅游行业的不断发展&#xff0c;越来越多的旅行社开始推出各种优惠卡来吸引游客。而随着智能手机的普及&#xff0c;开发一款旅行社优惠卡APP软件成为了一种必然的趋势。 该软件的主要功能是提供旅行社的各种优惠卡信息&#xff0c;包括优惠卡的种类、价格、使用范围、有效…

【代码随想录 | Leetcode | 第四天】数组 | 螺旋矩阵 | 螺旋矩阵 II

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来螺旋矩阵的分享✨ 目录 前言59. 螺旋矩阵 II54. 螺旋矩阵总结 59. 螺旋矩阵 II 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n…