当页面渲染太多标签时, 会出现卡顿的, 典型就是类似 table 数据太多时, 非常卡顿. 如果选择分页, 没必要讨论, 这儿只讨论采用滚动的情况. 解决思路很简单, 就是页面不展示出来的元素, 从页面上删除掉, 最难点在于滚动条的处理, 这儿分享一些细节思路, 以上下滚动为例.
上下滚动表格
每一行固定高度, 一次性获取所有数据.
每一行不固定高度, 一次性获取所有数据.
每一行不固定高度, 分批获取数据.
首先, 布局如下:
当只显示可视区的内容时, overflow 的标签需要删除掉, 但是删除了之后, 滚动条会变化, 甚至消失, 因此可添加 padding-top 和 padding-bottom, 以此模拟内容高度.
第一类, 所有数据都能根据计算获得, 需要一个 scrollTop 对应的显示数据的对照表, 当滚动条位置变化时, 去对照表种查看需要显示的数据, 以此来渲染. 当然不是每个 scrollTop 都去生成对照表, 只需要某个范围生成就行了, 比如:[{2000: 显示数据}, {5000: 显示数据}](表示分别表示 0-2000,2000-5000 显示的数据) 去对比第一个大于 scrollTop 的数据, 获取其值, 就是需要显示的数据.
** 这儿需要注意的是, 显示数据必须有重复, 且重复能占满屏幕以上, 避免出现空白 (第一次是 0-100 条, 第二次是 80-180 条)*
第二类, 就不好计算了, 比如某一格里面内容太多, 会令整行高度增加. 可采用隐藏标签 (opacity:0), 循环渲染每一行, 拿到那一行的高度. 此种方式简单, 也容易实现, 不过计算渲染数据时, 保证屏幕不出现空白的计算会复杂一点. 隐藏标签渲染时, 使用分批渲染, 比如每次渲染 10 行, 使用 requestAnimationFrame,setTimeout 或者 promise 处理一下, 不至于卡死.
第三类, 只知道当前数据是多少, 无法计算总高度. 可以采取与第二种类似的方式, 使用隐藏标签计算出每一行的高度, 最终计算出得到数据的总高度. 当滚动条滚到某个值时, 触发后续数据获取. 一样的方式, 重新计算出总高度.
所有方法都有个前提, 就是每一行数据渲染是同步的, 有些情况是先渲染出框, 等获取数据后填充框. 这种类似 table 的布局, 会非常麻烦, 需要设置一个回调函数, 等所有数据渲染完成后再获取高度.
还有一种方式, 或许会更简单, 但是效果上会差一些. 方法就是在滚动条距离底部某个位置的时候, 触发记录:
记录这一批次每一行元素的 offsetTop
计算出此批次数据对照的 scrollTop 以及此批次数据对应的 scrollHeight
记录 scrollHeight(往回滚动时用).
还需要在此时切换数据, 新批次数据必须有重复数据, 避免空白. 这样就可以边滚动, 边记录, 最终记录完成所有行数据的 offsetTop,scrollTop 范围对应的批数据, 以及此批的 scrollHeight. 父元素的 paddingTop 永远是那批次数据第一行的 offsetTop, 而最大的 scrollHeight - 当前批次数据的 scrollHeight = paddingBottom.
其他优化, 举例 vue, 可以使用 Object.freeze() 冻结只需要显示的数据, 尽量保证页面元素少, 是优化卡顿的有效方式, 所以, 能用 v-if, 尽量不要用 v-show, 能够销毁的组件, 不必留着, 如果为了减少请求, 应当保存数据而不是保存标签, keep-alive 非必要不要使用. 保存标签很容易出问题, 比如使用 v-if 弹窗表单组件, 需要手动清空数据, 而直接销毁, 代码会非常简洁. 重新渲染花费不了多少时间的. 如果计算量实在太大, 可以使用分批计算, 异步方式处理. 其作用就是在处理间隙, 让用户的操作事件能够响应.
来源: https://www.cnblogs.com/gsgs/p/11497988.html