react 高阶组件

2023-10-07  本文已影响0人  暴躁程序员

一、react 高阶组件 Higher-Order Components (简称为 HOC)

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。
HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

高阶函数:接受单个或多个函数作为参数并返回一个新函数的函数
高阶组件:接受单个或多个组件作为参数并返回一个新组件的函数

二、HOC 的种类

1. 属性代理

通过高阶组件将属性传递给被包装的原始组件,在原始组件中通过 this.props 操作属性

  1. 在组件中使用高阶组件
import React, { Component } from "react";
import HeightComponent from './pages/HeightComponent'
class App extends Component {
  render() {
    return (
      <>
        <HeightComponent a="a" />
      </>
    );
  }
}
export default App;
  1. 高阶组件
    定义高阶组件并在高阶组件中做通用逻辑处理
import React, { Component } from "react";

// 定义高阶组件
const HocPropsProxy = (TargetComponent) => {
  // 返回容器组件
  return class Enhance extends Component {
    constructor(props) {
      super(props);
      this.state = {
        b: "b",
      };
    }
    render() {
      return (
        <>
          <TargetComponent {...this.props} {...this.state} />
        </>
      );
    }
  };
};

// 定义原始组件
class Test extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      <>
        <div>
          <div>hello world</div>
          <div>a: {this.props.a}</div>
          <div>b: {this.props.b}</div>
        </div>
      </>
    );
  }
}

// 使用高阶组件包装原始组件
export default HocPropsProxy(Test);

2. 反向继承

在高阶组件中,让容器组件继承原始组件

  1. 在组件中使用高阶组件
import React, { Component } from "react";
import HeightComponent from './pages/HeightComponent'
class App extends Component {
  render() {
    return (
      <>
        <HeightComponent a="a" />
      </>
    );
  }
}
export default App;
  1. 定义高阶组件并在高阶组件中做通用逻辑处理
import React, { Component } from "react";

// 定义高阶组件
const HocPropsProxy = (TargetComponent) => {
  // 返回容器组件
  return class Enhance extends TargetComponent {
    constructor(props) {
      super(props);
      this.state = {
        b: "b",
      };
    }
    render() {
      return super.render()
    }
  };
};

// 定义原始组件
class Test extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  render() {
    return (
      <>
        <div>
          <div>hello world</div>
          <div>a: {this.props.a}</div> {/* 来自继承 */}
          <div>b: {this.state.b}</div>
        </div>
      </>
    );
  }
}

// 使用高阶组件包装原始组件
export default HocPropsProxy(Test);

三、HOC 常用示例

  1. redux 中的 connect
  2. react-router 中的 withRouter

四、高阶组件的拓展示例(分离通用样式和通用模板)

import React, { Component } from "react";
import styled from "styled-components";


// 添加公共样式
const Wrapper = styled.div`
  height: 100vh;
  width: 94%;
  margin-left: 3%;
  font-size: 24px;
  background: #f3f3f3;
  color: #666;
`;

// 定义高阶组件
const CommonCssWrapper = (TargetComponent) => {
  // 返回容器组件
  return class Enhance extends Component {
    render() {
      return (
        <>
          <Wrapper>
            <h1>react 高阶组件</h1> {/* 添加模板内容 */}
            <TargetComponent />
          </Wrapper>
        </>
      );
    }
  };
};

// 定义原始组件
class Test extends Component {
  render() {
    return (
      <>
        <div>
          <div>hello world</div>
        </div>
      </>
    );
  }
}

// 使用高阶组件包装原始组件
export default CommonCssWrapper(Test);

五、HOC 注意事项

1. 不能在无状态组件(函数类型组件)上使用 ref 属性
因为无状态组件没有实例
2. refs 属性不能透传
如果将 ref 添加到 HOC 的返回组件中,那么 ref 引用指向容器组件,而不是被包装的原始组件
4. 不要在 render 渲染方法中使用高阶组件
因为每次 render 函数在执行时,都会卸载和重新加载高阶组件,会造成状态丢失
5. 静态方法丢失
因为原始组件被包裹于一个容器组件内,所以高阶组件最终返回的组件没有原始组件的静态方法
但是可以通过 hoist-non-react-statics 脚本库做处理,实现静态方法拷贝
6. 不要以任何方式改变原始组件
上一篇 下一篇

猜你喜欢

热点阅读