IntersectionObserver实现小程序长列表优化
IntersectionObserver实现小程序长列表优化
关于 IntersectionObserver
思路
这里以一屏数据为单位【一个分页的10条数据,最好大于视口高度】,
监听每一屏数据和视口的相交比例,即用户能不能看到它
只将可视范围的数据渲染到页面上,其余的使用空白高度占位符代替,
可视范围可扩大到当前可视范围的上下两倍到三倍,减少滚动时留白现象
实现
大多数都是监听 scroll,结合防抖函数,来控制数据的渲染
这里我们使用小程序自带api,IntersectionObserver 来实现
小程序 IntersectionObserver
通过 IntersectionObserver 来监听可视范围内的元素,当元素进入可视范围时,将对应的数据渲染到页面上。
其返回的 intersectionRatio 为相交比例,大于0 说明进入可视范围,渲染真实数据,否则,渲染高度占位符
第一步
首先需要两个数组,一个用来存放真实数据,一个用来存放高度占位符数据
将原来的 storeList,改为二维数组,以一屏为单位进行分割
// Taro// wholePageHeight和wholeStoreList不用放在state中,页面销毁时记得释放// 高度占位符数据
let wholePageHeight = [];
// 真实数据
let wholeStoreList = [];state = {// 当前页码pageCurrent: 0,// 渲染的数据storeList: [],// 高度占位符数据storeListPlaceholder: [],// ...
}
第二步
获取界面上的节点信息
保存所有的列表数据以及页面高度数据
每次数据请求完成,将列表数据push到 wholeStoreList 中,
然后将当前这一屏的数据放到对应页面的 pageCurrent 的 storeList 中,
setState后, 计算这一屏的高度,然后将其存放到 wholePageHeight
// Taro// 分页获取列表数据
getList = async () => {// 接口请求数据const { pageCurrent } = this.state;const records = await api.getList({pageCurrent});// 分页累加pageCurrent++// 保存所有的列表数据wholeStoreList.push(records);// 设置当前这一屏的数据storeList[pageCurrent] = records;this.setState({storeList,pageCurrent,}, () => {// 数据setState后,获取当前页的高度this.getPageHeight();});
}// 计算当前页的高度
getPageHeight = () => {const {pageCurrent,} = this.state;// 返回一个 SelectorQuery 对象实例const query = Taro.createSelectorQuery();// 查询节点信息的对象query// 在当前页面下选择第一个匹配选择器 selector 的节点。返回一个 NodesRef 对象实例,可以用于获取节点信息。// 类似于 CSS 的选择器.select(`#storePage${pageCurrent}`)// 添加节点的布局位置的查询请求,SelectorQuery.exec 方法后,节点信息会在 callback 中返回.boundingClientRect()// 执行所有的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。.exec(res => {if (res && res[0].height) {/*** rect.id // 节点的ID* rect.dataset // 节点的dataset* rect.left // 节点的左边界坐标* rect.right // 节点的右边界坐标* rect.top // 节点的上边界坐标* rect.bottom // 节点的下边界坐标* rect.width // 节点的宽度* rect.height // 节点的高度*/// 保存当前页的高度wholePageHeight.push(res[0].height);// 监听当前页的节点this.observePage(pageCurrent);}});
}
第三步
针对每一屏都去添加监听,判断是否需要渲染真实数据,还是高度占位符
这里通过 IntersectionObserver 来监听,当元素进入可视范围时,将对应的数据渲染到页面上。
:::tip 小细节
如果只控制一屏的显示,那么当用户快速滑动上下屏时,
会出现一屏的数据还没渲染完,就已经滚动到下一屏了,导致白屏出现
所以:需要设置 relativeToViewport top 和 bottom 参数,顶部和底部的边界,进入上下三个屏幕高度就开始渲染
:::
// TaroobservePage = () => {const {storeList,} = this.state;const windowHeight = Taro.systemInfo.windowHeight;// WXML节点布局相交状态// 创建 IntersectionObserver 对象,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。const observerObj = Taro.createIntersectionObserver(this)// 指定页面显示区域作为参照区域之一.relativeToViewport({// 设置顶部和底部的边界,进入上下三个屏幕高度就开始渲染top: 3 * windowHeight, bottom: 3 * windowHeight});// 返回IntersectionObserver对象实例,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见observerObj.observe(`#storePage${pageIndex}`, (res) => {/*** res.id // 目标节点 id* res.dataset // 目标节点 dataset* res.intersectionRatio // 相交区域占目标节点的布局区域的比例* res.intersectionRect // 相交区域* res.intersectionRect.left // 相交区域的左边界坐标* res.intersectionRect.top // 相交区域的上边界坐标* res.intersectionRect.width // 相交区域的宽度* res.intersectionRect.height // 相交区域的高度*/// < 0,未相交,使用高度占位符if (res.intersectionRatio <= 0) {storeList[pageIndex] = {height: wholePageHeight[pageIndex]}// > 0,相交,使用真实数据} else {storeList[pageIndex] = wholeStoreList[pageIndex];}this.setState({storeList});});
}
第四步
在页面上渲染数据,如果当前这一屏有数据,就渲染真实数据,否则渲染高度高度占位符
// Taro// 列表渲染
renderStoreList = () => {const {storeList,} = this.state;return (storeList.map((storePage, index) => (<View className='store-page' key={index} id={'storePage' + index}>{// 是否存在当前页的数据storePage && storePage.length ?<View className='store-list'>{storePage.map((storeItem) => (<StoreInfo item={storeItem} key={storeItem.id} />))}</View>:// 占位组件 ---<PlaceWrap customStyle={{height: storePage.height + 'px'}} />}</View>)))
};
到此,一个长列表的优化就OK了
IntersectionObserver
看了下 caniuse ,发现除了IE,兼容性也还行,那web端也可以尝试下的

相关文章:
IntersectionObserver实现小程序长列表优化
IntersectionObserver实现小程序长列表优化 关于 IntersectionObserver 思路 这里以一屏数据为单位【一个分页的10条数据,最好大于视口高度】, 监听每一屏数据和视口的相交比例,即用户能不能看到它 只将可视范围的数据渲染到页面上&#x…...
Nginx动静分离、资源压缩、负载均衡、黑白名单、防盗链等实战
一、前言 Nginx是目前负载均衡技术中的主流方案,几乎绝大部分项目都会使用它,Nginx是一个轻量级的高性能HTTP反向代理服务器,同时它也是一个通用类型的代理服务器,支持绝大部分协议,如TCP、UDP、SMTP、HTTPS等。 二、…...
Rust之枚举与模式匹配
枚举类型,简称枚举,允许列举所有可能的值来定义一个类型。 1、定义枚举: 枚举类型:已知所有可能的值,并且所有值的出现是互斥的,即每次只能取一种可能的值,才使用枚举类型。 示例:…...
nfs服务器的描述,搭建和使用
前言 这是我在这个网站整理的笔记,关注我,接下来还会持续更新。 作者:RodmaChen nfs服务器的描述,搭建和使用 NFS概述工作原理优缺点 nfs服务器搭建服务端客户端 NFS概述 NFS(Network File System)是一种基…...
libuv库学习笔记-filesystem
Filesystem 简单的文件读写是通过uv_fs_*函数族和与之相关的uv_fs_t结构体完成的。 note libuv 提供的文件操作和 socket operations 并不相同。套接字操作使用了操作系统本身提供了非阻塞操作,而文件操作内部使用了阻塞函数,但是 libuv 是在线程池中调…...
记录vue的一些踩坑日记
记录vue的一些踩坑日记 安装Jq npm install jquery --save vue列表跳转到详情页,再返回列表的时候不刷新页面并且保持原位置不变; 解决:使用keepAlive 在需要被缓存的页面的路由中添加:keepAlive: true, {path: /viewExamine,nam…...
Mybatis学习笔记
Mybatis 文章目录 Mybatis搭建环境创建Maven工程将数据库中的表转换为对应的实体类配置文件核心配置文件mybatis-config.xml创建Mapper接口映射文件xxxMapper.xmllog4j日志功能 Mybatis操纵数据库示例及要点说明获取参数的两种方式${}#{} 各种类型的参数处理单个字面量参数多个…...
网络编程(11):三次握手和四次挥手部分细节(后续补充)
关于listen 服务器如果不listen,TCP协议栈就无法从CLOSED状态变成LISTEN状态,客户端发起连接,TCP协议栈会直接返回RST报文,从而导致客户端连接失败 关于accept accept发送在三次握手完成之后,从全连接队列中取出一个节…...
MySQL学习笔记 ------ 子查询
#进阶7:子查询 /* 含义: 出现在其他语句中的select语句,称为子查询或内查询 外部的查询语句,称为主查询或外查询 分类: 按子查询出现的位置: select后面: 仅仅支持标量子查询 …...
自然语言处理应用程序设计
原文地址:https://zhanghan.xyz/posts/22426/ 文章目录 一、摘要二、数据集三、相关环境四、功能展示1.系统主界面2.中文分词3.命名实体识别4.文本分类5.文本聚类6.其他界面 五、源码链接 一、摘要 将自然语言处理课程设计中实现的模型集成到自然语言处理应用程序…...
LeetCode 436. Find Right Interval【排序,二分;双指针,莫队】中等
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
正则表达式 —— Sed
Sed Sed 类似于vim就是一个文本编辑器,按行来进行编辑和排序 Sed的原理:读取,执行,显示 读取:读取文本内容之后,读取到的内容存放到临时的缓冲区—模式空间 执行:在模式空间,根据…...
TypeScript中数组,元组 和 枚举类型
数组 方式一 let arr: number[] [1, 2, 3, 4]方式二,使用泛型定义 let arr: Array<number> [1, 2, 3, 4]方式三,使用any let arr: any[] [12, string, true] console.log(arr[1]) // string元组 可以定义不同类型定义类型顺序需保持一直 …...
MyBatis-Plus-Join 多表查询的扩展
文章目录 网站使用方法安装使用Lambda形式用法(MPJLambdaWrapper)简单的连表查询一对多查询 网站 官方网站:https://mybatisplusjoin.com/Github地址:https://github.com/yulichang/mybatis-plus-joinGitee地址:https…...
认清现实重新理解游戏的本质
认清现实重新理解游戏的本质 OVERVIEW 认清现实重新理解游戏的本质现实两条小路的启发四个动机1.当前的学习任务或工作任务太艰巨2.完美主义3.对未来太过于自信/无知4.大脑小看未来的收益 四个方法1.让未来的收益足够巨大2.让未来的收益感觉就在眼前3.玩游戏有恶劣的结果4.玩游…...
LeetCode 2050. Parallel Courses III【记忆化搜索,动态规划,拓扑排序】困难
本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章…...
ETHERNET/IP转RS485/RS232网关什么是EtherNet/IP?
网络数据传输遇到的协议不同、数据互通麻烦等问题,一直困扰着大家。然而,现在有一种神器——捷米JM-EIP-RS485/232,它将ETHERNET/IP网络和RS485/RS232总线连接在一起,让数据传输更加便捷高效。 那么,它是如何实现这一功…...
使用node内置test runner,和 Jest say 拜拜
参考 https://nodejs.org/dist/latest-v20.x/docs/api/test.html#test-runner 在之前,我们写单元测试,必须安装第三方依赖包,而从node 20.0.0 版本之后,可以告别繁琐的第三方依赖包啦,可直接使用node的内置test runner…...
《面试1v1》Kafka的架构设计是什么样子
🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪 🍅 技术交流:定期更新Java硬核干货,不定期送书活动 🍅 王哥多年工作总结:Java学习路线总结…...
比较常见CPU的区别:Intel、ARM、AMD
一、开发公司不同 1、Intel:是英特尔公司开发的中央处理器,有移动、台式、服务器三个系列。 2、ARM:是英国Acorn有限公司设计的低功耗成本的第一款RISC微处理器。 3、AMD:由AMD公司生产的处理器。 二、技术不同 1、Intel&…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
