zoukankan      html  css  js  c++  java
  • 高阶组件

     高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。

       高阶组件就是一个没有副作用的纯函数。

      不要改变原始组件,使用组合

       例如:Redux的connect方法

    // This function takes a component...
    function withSubscription(WrappedComponent, selectData) {
      // ...and returns another component...
      return class extends React.Component {
        constructor(props) {
          super(props);
          this.handleChange = this.handleChange.bind(this);
          this.state = {
            data: selectData(DataSource, props)
          };
        }
    
        componentDidMount() {
          // ... that takes care of the subscription...
          DataSource.addChangeListener(this.handleChange);
        }
    
        componentWillUnmount() {
          DataSource.removeChangeListener(this.handleChange);
        }
    
        handleChange() {
          this.setState({
            data: selectData(DataSource, this.props)
          });
        }
    
        render() {
          // ... and renders the wrapped component with the fresh data!
          // Notice that we pass through any additional props
          return <WrappedComponent data={this.state.data} {...this.props} />;
        }
      };
    }

    约定:贯穿传递不相关props属性给被包裹的组件

    render() {
      // 过滤掉专用于这个阶组件的props属性,
      // 不应该被贯穿传递
      const { extraProp, ...passThroughProps } = this.props;
    
      // 向被包裹的组件注入props属性,这些一般都是状态值或
      // 实例方法
      const injectedProp = someStateOrInstanceMethod;
    
      // 向被包裹的组件传递props属性
      return (
        <WrappedComponent
          injectedProp={injectedProp}
          {...passThroughProps}
        />
      );
    }

    约定:最大化的组合性

    // 不要这样做……
    const EnhancedComponent = withRouter(connect(commentSelector)(WrappedComponent))
    
    // ……你可以使用一个函数组合工具
    // compose(f, g, h) 和 (...args) => f(g(h(...args)))是一样的
    const enhance = compose(
      // 这些都是单独一个参数的高阶组件
      withRouter,
      connect(commentSelector)
    )
    const EnhancedComponent = enhance(WrappedComponent)

    单独一个参数的高阶组件,类似 connect 函数返回的,签名是Component => Component。输入和输出类型相同的函数确实是很容易组合在一起。

    约定:包装显示名字以便于调试

    function withSubscription(WrappedComponent) {
      class WithSubscription extends React.Component {/* ... */}
      WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
      return WithSubscription;
    }
    
    function getDisplayName(WrappedComponent) {
      return WrappedComponent.displayName || WrappedComponent.name || 'Component';
    }

    React Developer Tools便于调试,

    注意:

    不要在render方法内使用高阶组件

    原因: (差分算法,渲染性能问题)

    render() {
      // 每一次渲染,都会创建一个新的EnhancedComponent版本
      // EnhancedComponent1 !== EnhancedComponent2
      const EnhancedComponent = enhance(MyComponent);
      // 那引起每一次都会使子对象树完全被卸载/重新加载
      return <EnhancedComponent />;
    }

    必须将静态方法做拷贝

     1)可借助hoist-non-react-statics

    function enhance(WrappedComponent) {
      class Enhance extends React.Component {/*...*/}
      // 必须得知道要拷贝的方法 :(
      Enhance.staticMethod = WrappedComponent.staticMethod;
      return Enhance;
    }

    2)分别导出组件自身的静态方法。

    // Instead of...
    MyComponent.someFunction = someFunction;
    export default MyComponent;
    
    // ...export the method separately...
    export { someFunction };
    
    // ...and in the consuming module, import both
    import MyComponent, { someFunction } from './MyComponent.js';

    Refs属性不能贯穿传递

    如果你向一个由高阶组件创建的组件的元素添加ref应用,那么ref指向的是最外层容器组件实例的,而不是被包裹的组件。

    现在我们提供一个名为 React.forwardRef 的 API 来解决这一问题(在 React 16.3 版本中)

  • 相关阅读:
    SpringBoot 调用 K8s metrics-server
    Kubernetes 实战——有状态应用(StatefulSet)
    Kubernetes 实战——升级应用(Deployment)
    Kubernetes 实战——发现应用(Service)
    Kubernetes 实战——配置应用(ConfigMap、Secret)
    Java 集合使用不当,Code Review 被 diss了!
    30 个 ElasticSearch 调优知识点,都给你整理好了!
    关于线程池的面试题
    Java面试必问,ThreadLocal终极篇
    Java代码中,如何监控Mysql的binlog?
  • 原文地址:https://www.cnblogs.com/lyraLee/p/10510810.html
Copyright © 2011-2022 走看看