针对后端返回大量数据导致页面卡顿的问题,本文介绍利用window.requestAnimationFrame()实现列表切片渲染的方案。通过将数据分页并按帧加载,相比setTimeout能集中DOM操作并跟随屏幕刷新频率,显著提升页面响应速度与用户体验。
背景
当后端返回的数据量适中时,直接渲染通常不会出现问题。然而,当前业务需求要求表格的每一行都支持编辑操作(包括各类下拉选择和输入框),并在整体保存后再次进入时回显已填写的数据。目前遇到的主要问题是,尽管接口数据返回迅速,但页面在回显过程中出现明显的卡顿现象,导致用户体验较差。
问题排查
经过对代码的详细审查,并未发现明显的逻辑错误。代码实现相对简单,主要流程是等待接口数据返回后赋值给表格进行展示,但页面始终处于loading状态,导致界面响应迟缓。
问题解决
此前了解到列表可以通过切片方式渲染,即前端对数据进行分页处理,并按顺序依次加载。假设每页显示 limit 条记录,则数据可划分为 Math.ceil(total/limit) 个页面。随后可以使用 setTimeout 按顺序渲染各个页面,每次仅渲染一个页面。
- 使用setTimeout
const renderList(list = []){
const total = list.length
const page = 0
const limit = 200
const totalPage = Math.ceil(total / limit)
const render = (page) => {
if (page >= totalPage) return
setTimeout(() => {
for (let i = page * limit; i < page * limit + limit; i++) {
const item = list[i]
if(item) {
// ...这里写当前表格赋值逻辑
// this.tableData.push(item)
}
}
render(page + 1)
},0)
}
render(page)
}- 为了优化性能,建议使用 requestAnimationFrame 来替代 setTimeout。
readerList(list = []) {
const total = list.length
const page = 0
const limit = 10
const totalPage = Math.ceil(total / limit)
const render = (page) => {
if (page >= totalPage) return
for (let i = page * limit; i < page * limit + limit; i++) {
const item = list[i]
if(item) {
// ...这里写当前表格赋值逻辑
// this.tableData.push(item)
}
}
requestAnimationFrame(() => { render(page + 1) })
}
requestAnimationFrame(() => { render(page) })
}关于requestAnimationFrame
requestAnimationFrame
window.requestAnimationFrame() 用于告知浏览器需要执行动画,并要求浏览器在下次重绘之前调用指定的回调函数以更新动画。该方法接收一个回调函数作为参数,该函数将在浏览器下一次重绘前执行。注意:若希望在下次重绘前继续更新下一帧动画,回调函数内部必须再次调用 requestAnimationFrame()。此外,requestAnimationFrame() 仅执行一次。
相比 setTimeout 和 setInterval,requestAnimationFrame 具有以下两个主要优势:
- requestAnimationFrame 会将每一帧中的所有 DOM 操作集中处理,确保在一次重绘或回流中完成,且重绘或回流的时间间隔与浏览器的刷新频率紧密同步,通常该频率为每秒 60 帧。
- 对于隐藏或不可见的元素,requestAnimationFrame 不会触发重绘或回流,从而减少 CPU、GPU 和内存的使用量。
以上就是JS使用window.requestAnimationFrame()对列表切片进行渲染的详细内容,更多关于JS window.requestAnimationFrame()的资料请关注本站其它相关文章!