目录
前言
在现代 Web前端开发中,性能优化一直是个重要话题。尤其在数据量较大的情况下,页面的渲染性能会直接影响用户体验。使用虚拟滚动技术,可以有效解决大数据量下的渲染性能问题。本篇文章将带你深入了解虚拟滚动的应用,帮助你在Vue项目中优化页面渲染性能。
什么是虚拟滚动
虚拟滚动(Virtual Scrolling)是一种高效的渲染技术,主要用于处理大量数据的长列表或表格。其基本原理是只渲染当前视口内可见的元素,而对不可见的部分仅保留占位符。这种方法大幅减少了DOM节点的数量,从而提升了渲染性能和滚动流畅度。
虚拟滚动的核心有以下 4 点:
- 渲染可见元素:虚拟滚动只会渲染当前视口内的元素,而不是整个列表或表格。比方说,假设视口中只能显示10个元素,那么虚拟滚动技术只会渲染这10个元素,即使总数据量有上万个。
- 动态更新视口内容:当用户进行滚动操作 时,使用虚拟滚动技术可以动态更新可视区域内的内容。新进入视口的元素会被渲染,而离开视口的元素会被销毁,从而保持视口内元素的数量相对稳定。
- 减少DOM操作:由于只渲染了可视区域内的元素,虚拟滚动大幅减少了DOM操作的频率。这不仅提高了渲染速度,还减小了内存占用,从而提升了整体性能。
- 占位元素:为了确保滚动条的正确性,虚拟滚动技术通常会使用一个高度为所有元素总高度的占位元素。这种占位元素会占据整个列表的高度,从而使滚动条的行为与渲染所有元素时相同。
业务案例
我接到过一个需求,就是某个页面,需要展示多个人的地图行为轨迹,这个人数比较多,可能有上千人,由于后端限制,不能做成分页的形式,只能做成一个很长的、可以滚动的列表。如果数据少,一次性渲染也还好,数据多了,页面操作必然会有些卡顿的,这对页面性能消耗比较大。选择虚拟滚动,就能很好的解决这个问题。
实现方式
由于我这里是 Vue的项目,这里推荐一个很好用的第三方库:vue-virtual-scroller。
在 GitHub 上,可以看到针对 Vue2 或者 Vue3 的使用说明。
这里介绍下 Vue2 的使用方法:
通过 npm安装
npm install vue-virtual-scroller
main.js引入
import { RecycleScroller } from 'vue-virtual-scroller' // 虚拟滚动插件
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
Vue.component('RecycleScroller', RecycleScroller)
这里我用的是RecycleScroller,适用于列表每一项大小固定的情况。如果你的每一项的高度不固定,你可以使用DynamicScroller和DynamicScrollerItem来实现虚拟滚动。
在Vue页面中使用
template 部分
<div class="table-box">
<RecycleScroller class="scroller" :items="pointsData" :item-size="80" key-field="name" v-slot="{ item }">
<div class="scroller-item">
<img src="/avatar2.jpg" alt="" />
<div class="scroller-item-content">
<div>{
{ item.name }}</div>
<div>编号:{
{ item.equipmentCoding }}</div>
</div>
<div class="scroller-item-btn" @click="viewingTrajectories(item)">查看轨迹</div>
</div>
</RecycleScroller>
</div>
css 部分:
.table-box {
display: flex;
gap: 10px;
height: 400px;
.scroller {
width: 100%;
height: 100%;
.scroller-item {
display: flex;
justify-content: space-between;
align-items: center;
height: 70px;
padding: 10px 16px;
margin-bottom: 10px;
border-radius: 15px;
background: linear-gradient(180deg, #dee9ff 0%, #ffffff 100%);
box-shadow: 1px 1px 6px 0px rgba(163, 190, 244, 0.67);
border-radius: 4px 4px 4px 4px;
border: 1px solid #fff;
border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)) 1 1;
&:nth-last-child(1){
margin-bottom: 0;
}
> img {
width: 40px;
height: 40px;
border-radius: 100px;
}
> .scroller-item-content {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
gap: 4px;
font-size: 14px;
margin-left: 16px;
> div:nth-child(1) {
font-weight: 500;
color: #1d2129;
}
> div:nth-child(n + 2) {
font-weight: 400;
color: #86909c;
}
}
> .scroller-item-btn {
cursor: pointer;
user-select: none;
margin-left: auto;
margin-top: auto;
padding: 5px 16px;
border-radius: 20px;
border: 1px solid #0a57fe;
font-weight: 400;
font-size: 14px;
color: #0a57fe;
}
}
}
}
这里需要注意,如果你希望让子元素之间有间距,我设置了item-size="80",同时设置.scroller-item这个class 的样式的height 为 70px,以及设置它的margin-bottom:10px;,最后一个元素设置 margin-bottom: 0。
效果预览

可以看到,无论是鼠标滚轮,还是拖动滚动滑块,都可以有很流畅的滚动效果。
总结
通过引入虚拟滚动技术,我们可以显著提升大数据量列表的渲染性能和用户滚动体验。虚拟滚动通过只渲染可视区域的内容,减少了DOM操作和内存占用,解决了传统大数据量渲染带来的性能瓶颈问题。目前 Vue3 相关的 UI 框架,大部分组件都支持了虚拟滚动,可以直接用,但 Vue2 旧项目相关的虚拟滚动相对较少,可能部分业务场景,需要自己手动实现,比方说下拉选择框、表格等。后面我会深入研究,用虚拟滚动技术,改造现有的组件。希望这篇文章可以对你有所帮助。