面试备战录

100 阅读5分钟

1、虚拟列表是如何工作的?有哪些使用场景?

答:虚拟列表(Virtual List/Virtual Scrolling) 是一种 列表渲染优化技术。原理是:只渲染可见区域的元素,其余元素用占位符撑起滚动高度,随着用户滚动动态替换DOM

  • 为什么要虚拟列表?
    • DOM节点太多会导致浏览器渲染性能严重下降(上万条数据直接渲染会卡死)。
    • 其实屏幕上可见元素很有限,比如 10 个屏幕能显示 100 条,就没必要一次性渲染一万条。
  • 核心思路
    • 撑起总高度:通过一个大容器(div)模拟整个列表高度,保证滚动条正常。
    • 计算可见范围:根据scrollTop和容器高度,计算当前应该渲染的item索引范围。
    • 渲染窗口:只渲染这一小段数据,并通过paddingtranslateY把它放到正确位置。
    • 滚动更新:用户滚动时,实时计算可见范围,替换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(水合),绑定事件。