Day 12:组件模式

3 阅读1分钟

Day 12:组件模式

HOC(高阶组件)

接收组件,返回增强后的组件

function withLoading(Component) {
  return function WithLoading({ isLoading, ...props }) {
    if (isLoading) return <Loading />;
    return <Component {...props} />;
  };
}

const EnhancedComponent = withLoading(MyComponent);

Render Props

把"怎么渲染"交给子组件决定

class MouseTracker extends React.Component {
  state = { x: 0, y: 0 };
  
  render() {
    return (
      <div onMouseMove={e => this.setState({ x: e.clientX, y: e.clientY })}>
        {this.props.render(this.state)}
      </div>
    );
  }
}

// 使用
<MouseTracker render={({ x, y }) => <h1>{x}, {y}</h1>} />

// Hook 写法
function useMouse() {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const handler = e => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener('mousemove', handler);
    return () => window.removeEventListener('mousemove', handler);
  }, []);
  return pos;
}

组合模式

用 props 组合,简单灵活

function Card({ header, children, footer }) {
  return (
    <div className="card">
      <div className="header">{header}</div>
      <div className="body">{children}</div>
      <div className="footer">{footer}</div>
    </div>
  );
}

自定义 Hook

function useLocalStorage(key, initialValue) {
  const [value, setValue] = useState(() => {
    const stored = localStorage.getItem(key);
    return stored ? JSON.parse(stored) : initialValue;
  });
  
  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);
  
  return [value, setValue];
}

面试问题

问题答案要点
HOC vs Hook?HOC 包装组件,Hook 抽象逻辑
render props 缺点?嵌套地狱,Hook 更好
组合vs继承?优先组合