Skip to content

性能优化

shouldComponentUpdate

通过返回布尔值控制组件是否更新:

javascript
shouldComponentUpdate(nextProps, nextState) {
  return nextState.number % 2 === 0; // 偶数才更新
}

PureComponent

自动进行浅比较,避免不必要的渲染:

javascript
class PureComp extends React.PureComponent {
  render() {
    return <div>{this.props.value}</div>;
  }
}

React.memo

用于函数组件的记忆化:

javascript
const MemoCounter = React.memo(Counter);

// 自定义比较函数
const MemoComp = React.memo(Comp, (prevProps, nextProps) => {
  return prevProps.value === nextProps.value;
});

性能优化最佳实践

javascript
function App() {
  const [username, setUsername] = useState("zhufeng");
  const [count, setCount] = useState(0);

  // 缓存对象
  const displayData = useMemo(() => ({ count }), [count]);

  // 缓存回调函数
  const incrementCount = useCallback(() => {
    setCount((count) => count + 1);
  }, []);

  return (
    <div>
      <input value={username} onChange={(e) => setUsername(e.target.value)} />
      <MemoChildButton
        displayData={displayData}
        incrementCount={incrementCount}
      />
    </div>
  );
}

重要概念

合成事件 (SyntheticEvent)

React 实现的事件系统,与原生事件隔离,跨浏览器兼容。

批量更新 (Batching)

React 会将多个状态更新合并为一次渲染,提高性能。

受控组件与非受控组件

  • 受控组件:表单元素的值由 React state 控制
  • 非受控组件:表单元素的值由 DOM 自身控制

组件通信方式

  1. Props - 父子组件通信
  2. Callback - 子父组件通信
  3. Context - 跨层级通信
  4. Redux/Zustand - 全局状态管理
  5. Event Bus - 兄弟组件通信
  6. Ref - 直接访问子组件实例

性能优化(续)

17.1 React.memo 和 useMemo

React.memo 用于防止不必要的组件重新渲染:

javascript
// 仅当 props 变化时才重新渲染
const Button = React.memo(({ onClick, label }) => {
  console.log("Button rendered");
  return <button onClick={onClick}>{label}</button>;
});

useMemo 缓存计算结果:

javascript
const ExpensiveComponent = ({ items }) => {
  // 只有当 items 变化时才重新计算
  const sortedItems = useMemo(() => {
    console.log("Sorting items...");
    return [...items].sort((a, b) => a - b);
  }, [items]);

  return (
    <div>
      {sortedItems.map((item) => (
        <p key={item}>{item}</p>
      ))}
    </div>
  );
};

17.2 useCallback

缓存函数引用,防止子组件不必要的重新渲染:

javascript
const Parent = () => {
  const [count, setCount] = useState(0);

  // 只有当依赖项变化时,函数引用才会改变
  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return <Child onClick={handleClick} />;
};

17.3 代码分割和懒加载

javascript
import { lazy, Suspense } from "react";

const HeavyComponent = lazy(() => import("./HeavyComponent"));

export default function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

17.4 虚拟列表

对于长列表,使用虚拟滚动提高性能:

javascript
// 使用库如 react-window 或 react-virtualized
import { FixedSizeList } from "react-window";

const Row = ({ index, style }) => <div style={style}>Item {index}</div>;

export default function VirtualList() {
  return (
    <FixedSizeList height={600} itemCount={10000} itemSize={35} width="100%">
      {Row}
    </FixedSizeList>
  );
}