当前位置: 首页 > news >正文

Vue 长列表卡顿、滚动掉帧怎么办?一次性讲清楚

文章目录

    • 前言
    • Vue 长列表为什么一定会卡?
      • 1. v-for 渲染大量节点的真实代价
      • 2. DOM 数量过多,回流重绘是致命的
      • 3. 图文混排 + 复杂组件 = 雪上加霜
    • 核心解法:虚拟列表(Virtual List)
      • 1. 虚拟列表原理一句话版
      • 2. vue-virtual-scroller 快速上手 Demo
        • 安装
        • 基础示例(可直接跑)
        • 关键点解析
    • key 用不好,虚拟列表也救不了你
      • 错误示例
      • 正确示例
    • keep-alive 和组件卸载策略
      • keep-alive 的正确用法
      • 离开页面主动清理数据
    • IntersectionObserver 做懒加载
      • 图片懒加载示例
    • 实战结果:10 万级表格渲染
    • 总结

前言

在 Vue 项目里,只要一遇到长列表,很多同学第一反应都是:

“我这也没干啥啊,就是 v-for 渲染个列表,怎么就卡成 PPT 了?”

更狠一点的,产品一句话:

“这个页面数据有点多,可能十几万条吧。”

然后你就知道,这一页不优化是肯定过不去了。

这篇文章我们就从为什么卡开始,一步一步讲清楚Vue 长列表性能问题的本质,以及真正能落地的解决方案

Vue 长列表为什么一定会卡?

先说结论一句话版:

卡,不是 Vue 慢,是 DOM 太多。

1. v-for 渲染大量节点的真实代价

假设你写了这样一段代码:

<div v-for="item in list" :key="item.id"> {{ item.name }} </div>

如果list有 10 万条数据,意味着什么?

  • 浏览器里会真实创建10 万个 DOM 节点

  • 每次滚动都会涉及:

    • 布局计算(Layout)
    • 回流(Reflow)
    • 重绘(Repaint)
  • 任意一次父组件更新,都可能触发这些节点的 diff

这不是 Vue 的锅,这是浏览器物理极限的问题

2. DOM 数量过多,回流重绘是致命的

浏览器渲染流水线大概是:

JS → Style → Layout → Paint → Composite

当 DOM 数量过多时:

  • Layout 时间暴涨
  • Scroll 时频繁触发 repaint
  • FPS 掉到 30 以下,人眼就明显感觉卡

这也是为什么你会看到:

  • 滚动时页面发虚
  • 快速滑动直接“锁死”
  • 真机比模拟器还卡

3. 图文混排 + 复杂组件 = 雪上加霜

如果列表项里还有:

  • 图片
  • 自定义组件
  • 动态高度
  • hover / 动画

那每一行的渲染成本都会进一步放大。

所以,结论很清楚:

长列表,绝对不能一次性渲染完。

核心解法:虚拟列表(Virtual List)

虚拟列表的核心思想其实很简单:

只渲染“屏幕可见的那一小部分 DOM”,其他的用占位撑高度。

1. 虚拟列表原理一句话版

假设屏幕一次最多只能看到 20 行:

  • DOM 中永远只存在 20~30 行
  • 滚动时,复用 DOM 节点
  • 数据在变,DOM 不新增

这就是虚拟列表。


2. vue-virtual-scroller 快速上手 Demo

这是 Vue 里最成熟、最常用的方案之一。

安装
npminstallvue-virtual-scroller
基础示例(可直接跑)
<template> <RecycleScroller :items="list" :item-size="50" key-field="id" > <template #default="{ item }"> <div class="row"> {{ item.text }} </div> </template> </RecycleScroller> </template> <script setup> import { RecycleScroller } from 'vue-virtual-scroller' const list = Array.from({ length: 100000 }).map((_, i) => ({ id: i, text: `第 ${i} 行数据` })) </script>
关键点解析
  • item-size非常重要,最好是固定高度
  • key-field:告诉组件用哪个字段复用 DOM
  • 内部使用的是 DOM 复用,不是频繁创建/销毁

实测:10 万条数据,滚动依然 60 FPS。

key 用不好,虚拟列表也救不了你

很多列表性能问题,其实是key 用错了

错误示例

<div v-for="(item, index) in list" :key="index">

问题:

  • 数据插入 / 删除时
  • index 全部变化
  • Vue 会误以为所有节点都变了

正确示例

<div v-for="item in list" :key="item.id">

记住一句话:

key 一定要稳定、唯一、和业务语义一致。

keep-alive 和组件卸载策略

在分页列表或 Tab 场景中,经常会遇到:

“切换回来列表还在,但怎么感觉越来越卡?”

keep-alive 的正确用法

<keep-alive :max="2"> <router-view /> </keep-alive>
  • 控制缓存页面数量
  • 避免无限缓存导致内存膨胀

离开页面主动清理数据

onDeactivated(()=>{list.value=[]})

对于超大列表,离开页面就应该释放内存,不要心疼。

IntersectionObserver 做懒加载

对于图片、复杂组件,可以再加一层优化。

图片懒加载示例

constobserver=newIntersectionObserver(entries=>{entries.forEach(entry=>{if(entry.isIntersecting){entry.target.src=entry.target.dataset.src observer.unobserve(entry.target)}})})
  • 图片进入可视区才加载
  • 极大降低首屏压力

实战结果:10 万级表格渲染

优化前:

  • 首屏白屏 3~5 秒
  • 滚动 FPS < 30

优化后(虚拟列表 + 懒加载):

  • 首屏 < 500ms
  • 滚动稳定 60 FPS

总结

Vue 长列表优化,本质是“控制 DOM 数量”。
只要 DOM 在可控范围内,性能问题基本都能解决。

http://www.cnnetsun.cn/news/55500.html

相关文章:

  • Zotero-GPT插件API配置全流程解析与故障排查
  • Pyarmor解密工具:无需运行即可静态解密Python加密脚本的终极方案
  • 论文AI率太高?3款降AI软件实测对比,去除知网aigc痕迹!
  • 基于微服务架构的悟空人力资源管理系统设计与实现
  • 实测3款论文降AI率工具,一键搞定降AIGC率!
  • 网盘直链下载助手:告别客户端限制,开启高速下载新时代
  • NotepadNext十六进制编辑:二进制数据处理的终极指南
  • 基于微信小程序的在线摄影预约系统毕设
  • FF14自动跳过副本动画插件终极指南
  • 基于微信小程序的社区老年服务系统毕业设计源码
  • 统一场论质量定义方程:数学验证与应用分析
  • 10 Nacos 如何在集群中同步实例信息
  • 精选9款高效AI写作工具,帮助用户快速完成开题报告及学术论文创作。
  • 2025年数字人厂家热销榜单:解锁最佳技术实力与落地方案
  • PlugY终极指南:解锁暗黑2单机模式的7大隐藏功能
  • BibTeX国标排版神器:让学术写作告别格式焦虑
  • ISC3000-S U-Boot内置命令详解
  • 鲁棒控制实战宝典:从零掌握Tube MPC技术的完整指南
  • 10分钟精通League Akari:英雄联盟智能助手的全方位配置手册
  • uv-ui框架:重新定义多端开发的终极解决方案
  • 5分钟极速上手:Mermaid Live Editor文本绘图终极指南
  • 如何在浏览器中轻松创建专业Word文档:DOCX.js实用指南
  • 2025终极指南:LinkSwift网盘直链解析工具,一键获取高速下载链接
  • 24、深入探索XPath与XPointer:精准定位XML资源
  • 33、资源描述框架(RDF):语义网的关键技术
  • 43、MathML:发展、应用与关键技术解析
  • 百度ERNIE 4.5大模型震撼发布:多模态技术突破与开源生态构建
  • Nintendo Switch全能工具箱:NSC_BUILDER深度解析与实战指南
  • 联想拯救者工具箱完整使用指南:从入门到精通的全流程解析
  • 终极指南:用开源贴片机实现专业级电子制造