公共抽离之HOC和Render Props

27 阅读1分钟

什么是HOC

HOC全称是高阶函数组件,其本质就是一个函数。调用这个函数需要传入原来的组件返回一个新的增强组件。例如Redux的connect函数。

function withLocationQuery(Component){
   const queryParams = parserSearch(location.search) || {};
   return function LocationQueryComp(props){
      return (
         <Component {...queryParams} {...props} />
      )
   }
}

在👆🏻例子中withLocationQuery就是一个HOC,他将queryParams注入到了Component的props内。

注意📢!!!

HOC用来增强props时不可以修改组件原有的逻辑。

HOC能做的功能很多强化props只是其中一项,比如渲染劫持,生命周期拦截等等,但是常用的还是增强props。

什么是Render Props

Render Props是另一种代码抽离方案,他的使用场景是:当两个组件实现功能基本一致,但是UI大不相同时就可以使用Render Props。

举个例子

当鼠标移动时ChildCom1需要显示鼠标的位置,ChildCom2需要显示一个跟随的小球。

function App() {
  return (
    <div style={{
      display: 'flex',
      justifyContent: 'space-between',
      width: "850px"
    }}>
      <MouseMove>
        {(props) => <ChildCom1 {...props} />}
      </MouseMove>
      <MouseMove>
        {props => <ChildCom2 {...props} />}
      </MouseMove>
    </div>
  );
}

function MouseMove(){
   const [points, setPoints] = useState({
    x: 0,
    y: 0,
  });

  function handleMouseMove(e) {
    setPoints({
      x: e.clientX,
      y: e.clientY,
    });
  }

  return props.render ? props.render({ points, handleMouseMove }) : null;
}

function ChildCom1(props) {
  return (
      <div style={{
          width: '400px',
          height: '400px',
          backgroundColor: 'red'
      }} onMouseMove={props.handleMouseMove}>
          <h1>移动鼠标!</h1>
          <p>当前的鼠标位置是 ({props.points.x}, {props.points.y})</p>
      </div>
   );
 }
 
 function ChildCom2(props) {
  return (
    <div
      style={{
        width: "400px",
        height: "400px",
        backgroundColor: "grey",
        position: "relative",
        overflow: "hidden",
      }}
      onMouseMove={props.handleMouseMove}
    >
      <h1>移动鼠标!</h1>
      {/* 这里减去 460 是因为要减去左边 div 的宽度 + 两个大 div 之间 50 的间距 */}
      <div
        style={{
          width: "15px",
          height: "15px",
          borderRadius: "50%",
          backgroundColor: "white",
          position: "absolute",
          left: props.points.x - 5 - 460,
          top: props.points.y - 5 - 10,
        }}
      ></div>
    </div>
  );
}

一般来讲,Render Props 应用于组件之间功能逻辑完全相同,仅仅是渲染的视图不同。这个时候我们可以通过 Render Props 来指定要渲染的视图是什么。

而 HOC 一般是抽离部分公共逻辑,也就是说组件之间有一部分逻辑相同,但是各自也有自己独有的逻辑,那么这个时候使用 HOC 比较合适,可以在原有的组件的基础上做一个增强处理。