96SEO 2026-08-12 12:16 6
经常需要渲染上千甚至上万条长列表数据。
使用者痛点:

虚拟列表是长列表性能调整的合适方案,主要思想非常清晰:只渲染当前可视区域的 DOM 节点。销毁/缓存非可视区域内容,让页面始终维持极少 DOM 数量从根源解决大数据渲染卡顿问题。
目前多数开源方案基于固定高度实现,算法简单但业务兼容性极差。真实业务中,不定高虚拟列表才是覆盖绝大多数场景的通用方案。
| 方案类型 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 定高虚拟列表 | 算法简单、计算开销小、滚动响应丝滑 | 高度固定写死,无法适配动态内容;业务兼容性差 | 每行高度统一的简单结构化列表 |
| 不定高虚拟列表 | 自适应任意动态高度、无需手动传入高度、业务适配性极强 | 需要动态计算真实高度+缓存管理。算法复杂度略高 | 聊天记录、富文本列表、商品卡片、动态内容不规则列表等场景 |
不同于定高列表通过「索引 × 固定高度」快速定位,不定高虚拟列表面临未知高度、动态渲染、精准校正滚动位置的难题。
整套方案依赖以下三大主要能力:
import { ref。computed,watch,type Ref } from 'vue'
/** 虚拟列表配置参数 */
export interface VirtualListOptions {
/** 单次渲染可视条数 */
pageSize?: number
/** 条目预估兜底高度 */
estimateHeight?: number
}
/**
* Vue3 不定高虚拟列表 Hooks
* - 自动缓存真实高度
* - 动态计算可视区间
* - 滚动偏移精准校正
* - 支持全量刷新 & 增量分页加载
*/
export default function useVirtualList(
listData: Ref,options: VirtualListOptions = {}
) {
const { pageSize = 20。estimateHeight = 60 } = options
// 滚动容器 DOM 实例
const wrapperRef = ref
// 可视区域起止索引
const startIndex = ref
const endIndex = ref
// 当前滚动偏移量
const scrollOffset = ref
// 高度缓存:key=全局索引,value=真实 DOM 高度
const itemHeightCache = ref
/** 获取单条条目真实高度 */
const getItemHeight = : number => {
return itemHeightCache.value?,estimateHeight
}
/** 累计指定索引之前所有条目的总高度 */
const getItemTop = : number => {
let top = 0
for {
top += getItemHeight
}
return top
}
/** 列表整体总高度,用于撑开外层滚动条 */
const totalHeight = computed => {
let total = 0
listData.value.forEach => {
total += getItemHeight
})
return total
})
/** 当前可视区间渲染的数据 */
const visibleList = computed => {
return listData.value.slice
})
**/** 滚动监听主要原因:实时计算起止索引 & 更新 offset **/
const handleScroll = : void => {
if return
const scrollTop = wrapperRef.value.scrollTop
scrollOffset.value = scrollTop
let heightSum = 0
let startIdx = 0
for {
heightSum += getItemHeight
if {
startIdx = i
break
}
}
startIndex.value = startIdx
endIndex.value = startIdx + pageSize
}
/** 更新并缓存单条真实 DOM 高度 */
const updateItemHeight = :void=>{
if{
itemHeightCache.value=height
}
}
/** 全量重置 */
const resetVirtualList = :void=>{
startIndex.value = 0
endIndex.value = pageSize
scrollOffset.value = 0
itemHeightCache.value={}
if{
wrapperRef.value.scrollTop=0
}
}
/** 增量加载——仅拼接数据保留历史缓存 */
const appendListData=:void=>{
listData.value=
}
// 深度监听全量变化 → 自动全量重置
watch(listData。=>resetVirtualList,{ deep:true }
)
return{
wrapperRef,visibleList,totalHeight,scrollOffset,startIndex,endIndex,handleScroll,updateItemHeight,resetVirtualList,appendListData // 分页增量专用方法
}
}
updateItemHeight" class="list-item" ref="elRefs" v-for=" in visibleList">
{{ item.title }}
{{ item.desc }}
. . .
- 首次渲染使用预估占位。高度未知导致白屏闪烁 ‑ 渲染完成后立即采集真实 DOM 高度并写入缓存 ‑ 后续滚动直接复用缓存,无需 回流测量,实现“无抖动·无回弹”。
- 所有复杂计算与状态管理都封装在 #useVirtualList.ts#
‑ UI 层只负责结构与样式。无需关心任何数学运算
‑ 同一个 Hook 能在多种业务页面复用,实现“一套代码,多处使用”。
- 深度 watch 列表数组变化 ‑ 搜索 / 筛选 / 刷新时自动清空旧缓存并恢复滚动到顶部 ‑ 防止“旧数据残留导致错位”这类常见 bug。
- 使用 :style="{transform:`translateY`}"
‑ 根据实时累计偏移校正可视区域位置
‑ 解决问题不定高布局下的空白跳跃问题。
- 上拉加载下一页时仅调用 #appendListData#
‑ 保留历史 Height 缓存,不会出现回弹或抖动。
- 数据源被替换后 Hook 自动执行 #resetVirtualList#
‑ 清空旧缓存并重新计算所有 Height。
- 列表置顶 / 删除 / 编辑,只需更新数组 ‑ Hook 会同步更新对应索引的 Height 与可视区间。
User Pain Point:
#resetVirtualList##appendListData#。保留旧缓存,不触发重置,不过,
import { ref。computed,type Ref } from 'vue'
export interface VirtualListOptions{
pageSize?:number
estimateHeight?:number
}
/** Vue3 不定高虚拟列表 Hooks */
export default function useVirtualList(
listData:Ref,options:VirtualListOptions={}
){
const {pageSize=20。estimateHeight=60}=options
const wrapperRef=ref
const startIndex=ref
const endIndex=ref
const scrollOffset=ref
const itemHeightCache=ref
const getItemHeight==>itemHeightCache.value?,estimateHeight
const totalHeight=computed=>{
let t=0
listData.value.forEach=>t+=getItemHeight)
return t
})
const visibleList=computed=>listData.value.slice)
const handleScroll=:void=>{
ifreturn
const top=wrapperRef.value.scrollTop
scrollOffset.value=top
let sum=0,start=0
for{
sum+=getItemHeight
if{start=i;break}
}
startIndex.value=start
endIndex.value=start+pageSize
}
/** 缓存单条真实 Height */
const updateItemHeight==>{if{itemHeig…htCache.val,/** 全量重置 – 搜索/刷新/弹窗等情形调用 */
const resetVirtualL…st=>{,}
/** 增量拼接 – 分页加载专用 */
const appendLis…
ta==>{listDa…
value=}
return{
wrapperRef,visibleLis…不过,t,totalHeig…scrol,ffset,startI…handl,croll,u…updat,temHei…rese,tVir…appe,dLis…}
}
{handleScroll;checkBottom}""' class='"virtual-wrapper"' ref='"wrapperRef")'>
&/d iv>
&/t emplate&
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback