利用requestAnimationFrame优化大数据列表渲染

当我们拿到一个列表数据进行渲染时,如果数据量比较大,例如下面代码中模拟渲染一万条数据,可以看到很明显的卡顿,隔了几秒才看到列表展示。

js 复制代码
// 模拟返回10000数据
const mockData = () => {
    return Array(10000).fill({
      name: '张三',
      age: 18
    })
}
this.tableData = mockData()

应对这种情况,主流的方案一般采用虚拟滚动进行优化,本文则主要分享一下分片思想 + requestAnimationFrame的优化方式,仅供大家学习了解!

分片思想

大量数据同时渲染,可能会造成浏览器的阻塞导致页面长时间没反应,既然数据大是罪魁祸首,那我们可以尝试将数据分片,即把一份大的数据分成一份一份较小的数据片,分好之后再把逐个将其送给浏览器进行渲染。例如一万条数据,我们可以分成100份,一份100条,每一次只渲染100条,渲染完成后继续执行下一个任务,直至把所有数据渲染完为止。

requestAnimationFrame

requestAnimationFrame(callback)window下的一个方法,跟setTimeout用法类似,接收一个回调函数,该回调函数会在浏览器下一次重绘之前执行。只不过requestAnimationFrame的时间间隔是由浏览器自己决定的,浏览器为了保证流畅性,重绘频率会与系统刷新率保持一致,如果刷新率是60hz,即表示每秒刷新60次,也就是每次重绘的间隔时间大概是1000ms/60=16.6msrequestAnimationFrame会跟随浏览器的频率,每16.6ms回调函数就被执行一次,从而避免丢帧卡顿现象。

下面我们通过将数据分片放在requestAnimationFrame里执行渲染,渲染后继续执行下一个分片数据,递归调用直到所有数据渲染完毕。

js 复制代码
const mockData = () => {
    return Array(10000).fill({
      name: '张三',
      age: 18
    })
}
const totalData = mockData()
const pageNum = 100 // 每页条数
const totalPage = Math.ceil(totalData.length / pageNum) // 总共要分成几页
let page = 1
const renderList = () => {
    // 本次要渲染的数据
    const renderData = totalData.slice(
      (page - 1) * pageNum,
      page * pageNum
    )
    this.tableData.push(...renderData)
    page++

    if (page <= totalPage) {
      // 递归调用
      window.requestAnimationFrame(renderList)
    }
}

window.requestAnimationFrame(renderList)

对比效果可以发现同样是加载1万条数据,通过分片渲染的方式可以明显降低延迟或卡顿的现象。

相关推荐
雨季66617 分钟前
Flutter 三端应用实战:OpenHarmony 简易“动态内边距调节器”交互模式深度解析
javascript·flutter·ui·交互·dart
会飞的战斗鸡1 小时前
JS中的链表(含leetcode例题)
javascript·leetcode·链表
方也_arkling1 小时前
别名路径联想提示。@/统一文件路径的配置
前端·javascript
qq_177767372 小时前
React Native鸿蒙跨平台剧集管理应用实现,包含主应用组件、剧集列表、分类筛选、搜索排序等功能模块
javascript·react native·react.js·交互·harmonyos
qq_177767372 小时前
React Native鸿蒙跨平台自定义复选框组件,通过样式数组实现选中/未选中状态的样式切换,使用链式调用替代样式数组,实现状态驱动的样式变化
javascript·react native·react.js·架构·ecmascript·harmonyos·媒体
web打印社区2 小时前
web-print-pdf:突破浏览器限制,实现专业级Web静默打印
前端·javascript·vue.js·electron·html
烬头88212 小时前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu121382 小时前
Vuex介绍
前端·javascript·vue.js
2601_949809593 小时前
flutter_for_openharmony家庭相册app实战+相册详情实现
javascript·flutter·ajax
qq_177767373 小时前
React Native鸿蒙跨平台通过Animated.Value.interpolate实现滚动距离到动画属性的映射
javascript·react native·react.js·harmonyos