Q6 · 性能指标

如何用代码获取 FID?指标分数段?怎么提升?React 和 Vue 有什么差异?

FIDINP交互响应

⚡ 速记答案(30 秒)

  • 获取:PerformanceObserver 监听 first-input 条目,读取 processingStart - startTime
  • 分数段:好 < 100ms;一般 100–300ms;差 > 300ms
  • 减少主线程长任务、拆分计算、减少大块同步 JS
  • 提前绑定事件,首屏不要挂太多监听;使用 Web Worker 处理重计算
  • React 可利用 Concurrent Mode / useTransition 避免阻塞高优先级更新
  • Vue 通过响应式 + 批量更新减少不必要的 DOM 更新

📖 详细讲解

FID vs INP


FID:首次输入延迟(仅测量第一次交互)

INP:Interaction to Next Paint(测量所有交互,2024 年取代 FID)


优化策略


1. 减少主线程阻塞

• 拆分长任务

• 延迟非关键 JS

• 使用 Web Worker


2. 框架级优化


React

• 使用 useTransition 区分紧急和非紧急更新

• 使用 useDeferredValue 延迟渲染


Vue

• 利用响应式系统的批量更新

• 使用 v-once 静态优化

• 使用 shallowRef 减少深层监听

💻 代码示例

获取 FID 指标
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries() as any[]) {
    const fid = entry.processingStart - entry.startTime;
    console.log('FID:', fid, 'ms');
    observer.disconnect();
  }
});

observer.observe({ type: 'first-input', buffered: true });
React useTransition 示例
import { useState, useTransition } from 'react';

function SearchResults() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  const [isPending, startTransition] = useTransition();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 紧急更新:立即更新输入框
    setQuery(e.target.value);
    
    // 非紧急更新:延迟过滤结果
    startTransition(() => {
      setResults(filterResults(e.target.value));
    });
  };

  return (
    <div>
      <input value={query} onChange={handleChange} />
      {isPending && <span>加载中...</span>}
      <ResultList results={results} />
    </div>
  );
}
💡
面试技巧:回答性能问题时,先说指标和标准,再讲优化手段,最后结合实际项目经验。