1、虚拟列表是如何工作的?有哪些使用场景?
答:虚拟列表(Virtual List/Virtual Scrolling) 是一种 列表渲染优化技术。原理是:只渲染可见区域的元素,其余元素用占位符撑起滚动高度,随着用户滚动动态替换DOM。
- 为什么要虚拟列表?
DOM节点太多会导致浏览器渲染性能严重下降(上万条数据直接渲染会卡死)。- 其实屏幕上可见元素很有限,比如 10 个屏幕能显示 100 条,就没必要一次性渲染一万条。
- 核心思路
- 撑起总高度:通过一个大容器(
div)模拟整个列表高度,保证滚动条正常。 - 计算可见范围:根据
scrollTop和容器高度,计算当前应该渲染的item索引范围。 - 渲染窗口:只渲染这一小段数据,并通过
padding或translateY把它放到正确位置。 - 滚动更新:用户滚动时,实时计算可见范围,替换
DOM节点。
- 撑起总高度:通过一个大容器(
- 复杂情况
- 固定高度:实现简单,可直接用
index * itemHeight计算位置。 - 不定高度:需要
提前测量或缓存高度,动态更新可见区范围。
- 固定高度:实现简单,可直接用
- 常用场景:
长列表(几千 ~ 上万条数据)、聊天窗口、大数据表格、无限滚动 feed 流。
2、首屏加载优化有哪些常用手段?
答:首屏加载优化的目标是:用户打开页面时尽快看到主要内容,提升“首屏时间”和“感知性能”。常用手段包括:资源体积优化、请求数量减少、并行加载、懒加载、SSR/预渲染等。
- 减少资源体积
- 代码压缩(
JS、CSS、HTML) Tree Shaking(去除未用代码)- 图片优化(WebP、懒加载、雪碧图、压缩)
- 按需加载第三方库(选择合适的第三方库)
- 代码压缩(
- 减少请求数量 & 提升并行度
- 合并资源(打包策略合理化)
- 使用
CDN分发静态资源 HTTP/2/3多路复用,减少连接开销
- 资源加载顺序优化
JS使用async/defer,避免阻塞渲染CSS放头部,JS放尾部(或defer)Critical CSS(关键样式内联,非关键异步加载)
- 首屏直出
SSR(服务端渲染):后端直出HTML,首屏更快。Prerender(预渲染):打包时生成静态HTML。- 骨架屏:先展示占位
UI,避免白屏。
- 缓存利用
HTTP缓存(Cache-Control、ETag)Service Worker缓存静态资源- 本地缓存数据,减少接口请求
- 接口优化
- 减少首屏请求接口数量(合并接口、
GraphQL) - 接口数据裁剪(只返回首屏必要字段)
- 使用预取(prefetch)/预加载(preload)
- 减少首屏请求接口数量(合并接口、
例:假设一个 React/Vue 项目:
- 打包时用 代码分割:
import()异步加载路由组件,首屏只加载必要代码。 - 首页
CSS关键部分用Critical CSS内联,其余延迟加载。 - 图片用懒加载,首屏之外的图片不加载。
- 使用骨架屏或Loading占位,避免白屏
- 部署静态资源到
CDN,同时启用Gzip/Brotli压缩。
3、组件的渲染优化技巧有哪些?(如 React 的 memo、Vue 的 keep-alive)
答:组件渲染优化的目标是减少不必要的重新渲染,提高性能。常用手段包括:缓存组件、控制依赖、懒加载、列表渲染优化等。
React 常用优化技巧
React.memo:对函数组件做浅比较,避免 props 未变化时重新渲染。useMemo/useCallback:缓存计算结果和函数引用,避免每次渲染生成新对象导致子组件不必要渲染。- 列表渲染优化:
key唯一,配合React.memo避免整列表重新渲染。对大列表可用虚拟列表(react-window/react-virtualized)。 - 懒加载组件:
React.lazy + Suspense,按需加载组件,减少首屏渲染压力。
Vue 常用优化技巧
keep-alive:缓存组件实例,切换时复用,避免销毁和重新渲染。v-once:组件或元素只渲染一次,静态内容不重复渲染。computed / watch:避免在模板里做复杂计算,计算结果缓存依赖变化。- 列表渲染优化:
v-for用唯一key;对大列表可配合虚拟滚动组件(如vue-virtual-scroller)。 - 动态组件懒加载:
defineAsyncComponent按需加载组件。
通用优化策略
- 避免匿名函数/对象/数组直接在模板或
props里传递(会导致浅比较失效) - 避免大组件树频繁全局状态变更(用局部状态或
context/store分片) - 对静态内容或不常变化内容使用缓存策略
4、服务端渲染(SSR)和客户端渲染(CSR)性能对比
- CSR(客户端渲染):服务端只返回空
HTML + JS,浏览器下载并执行 JS 后才渲染页面。- 首屏慢(白屏时间长),但后续页面切换快,前后端分离灵活
- SSR(服务端渲染):服务端在请求时就拼好
HTML返回,浏览器立即能看到内容。- 首屏快,对
SEO友好,但服务端压力大,渲染过程复杂。
- 首屏快,对
- CSR 流程:
- 浏览器请求
HTML(很轻量,几乎只有<div id="app"></div>+JS引用)。 - 浏览器下载
JS→ 解析/执行 →生成DOM→ 渲染页面。 - 首屏依赖 JS 下载+执行+数据请求,容易导致白屏。
- 浏览器请求
- SSR 流程:
- 浏览器请求
HTML→ 服务端执行框架逻辑(React/Vue等)生成 完整HTML。 - 浏览器直接渲染出首屏内容(无白屏)。
- 浏览器再下载并执行
JS,进行hydrate(水合),绑定事件。
- 浏览器请求