代理以及继承方式的高阶组件
上一篇文章介绍了简单的高阶组件实现方式,接下来介绍代理和继承方式的高阶组件。
一、代理方式的高阶组件
应用场景:
1. 操纵props
高阶组件能够改变被包裹组件的 props ,可以对 props 做任何操作,甚至可以在高阶组件中自定义事件,然后通过 props 传递下去。
上一篇实现了一个简单的高阶组件,下面介绍如何在高阶组件中传递被包裹组件的属性:
App.js
import React from 'react';
import B from './components/B';
import C from './components/C';
import './index.css';
class App extends React.Component {
  render() {
    return(
      
          头部 
          
            头部 
          
      )
    }
  }
};
export default hocA;
页面效果
image.png
如何通过高阶组件给被包裹组件增加属性
A.js
import React, { Component } from 'react';
function hocA(Wrapper) {
  return class A extends Component {
    render() {
      return (
        
          头部 
          
      )
    }
  }
};
export default hocA;
B 组件中使用该属性,B.js
import React, { Component } from 'react';
// 引入该高阶组件
import hocA from './A';
class B extends Component {
  render() {
    return (
      
        
    )
  }
}
export default hocA(B);
页面效果
image.png
如何通过高阶组件删除被包裹组件的属性
改写后的 A.js
import React, { Component } from 'react';
function hocA(Wrapper) {
  return class A extends Component {
    render() {
      {/* 将props都解构出来,除了age属性以外的其它属性都用newProps来存放 */}
      const { age, ...newProps } = this.props;
      return (
        
          头部 
          
            头部 
          
            头部 
          
      )
    }
  }
};
export default hocA;
B.js
import React, { Component } from 'react';
import hocA from './A';
class B extends Component {
  render() {
    return (
      
          头部 
          
      )
    }
  }
};
export default hocA;
B.js
import React, { Component } from 'react';
import hocA from './A';
class B extends Component {
  render() {
    return (
      
          头部 
          
            
        {/* 这里传递name和age属性给B组件 */}
        
        
    )
  }
}
export default App;
A.js
import React, { Component } from 'react';
function hocA(Wrapper) {
  return class A extends Component {
    render() {
      return (
        
          姓名:{this.props.name}
        
        
          年龄:{this.props.age}
        
        
          这是B组件
        
      
            {/* 将传递到高阶组件的属性解构出来并传递给被包裹属性 */}
            
        
            {/* 增加sex属性 */}
            
        
          姓名:{this.props.name}
        
        
          年龄:{this.props.age}
        
        
          性别:{this.props.sex}
        
        
          这是B组件
        
      
          这是B组件
        
      
            { /* 把状态和方法传给被包裹组件 */ }
            
        
        { /* 让高阶组件帮我们实现输入框受控 */ }
        
        
    )
  }
}
export default hocA(B);
C.js
import React, { Component } from 'react';
import hocA from './A';
// 装饰器语法使用该高阶组件
@hocA
class C extends Component {
  render() {
    return (
      
          这是B组件
        
      
        { /* 让高阶组件帮我们实现输入框受控 */ }
        
        
    )
  }
}
export default C;
页面效果
image.png
这样我们就在高阶组件中把公用状态抽离出来,提高了代码的复用性。
4. 包装组件
包装组件很简单,我们前面就使用了该特性,所谓包装组件就是添加一系列标签,让被包裹组件实现想要的样式。
image.png
二、继承方式的高阶组件
采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是Wrapper,那么返回的组件就直接继承自 Wrapper 。
和代理方式的高阶组件的区别
image.png
两者继承的类不同。代理方式的高阶组件继承自 React.Component,继承方式的高阶组件则是继承自传入的参数组件 。
render 函数中 return 出去的东西不同。代理方式的高阶组件返回的是传入的参数组件,继承则是返回 super.render(),渲染出参数组件。
应用场景:
1. 操纵props
使用继承方式的高阶组件给参数组件添加属性
A.js
import React from 'react';
function hocA(Wrapper) {
  return class A extends Wrapper {
    render() {
      // 拿到参数组件的元素
      const element = super.render();
      const newStyle = {
        // 如果参数组件元素的最外层是div标签则返回红色,否则返回绿色
        color: element.type === 'div' ? 'red' : 'green',
      };
      const newProps = { ...this.props, style: newStyle };
      return (
        
          这是C组件
        
      
            {React.cloneElement(element, newProps, element.props.children)}
          
        
        这是B组件
      
    )
  }
}
export default hocA(B);
C.js
import React, { Component } from 'react';
import hocA from './A';
// 装饰器语法使用该高阶组件
@hocA
class C extends Component {
  render() {
    return (
      
        这是组件C
      
    )
  }
}
export default C;
效果
image.png
实际过程中除非需要通过传入的参数组件来判断性地去修改一些属性,否则没有必要使用继承方式高阶组件去操纵props。
2. 操纵生命周期函数
继承方式的高阶组件需要修改生命周期函数时直接在高阶组件内重写生命周期函数即可,它会覆盖掉参数组件的生命周期函数。
从上面可以看出来,代理方式的高阶组件要优于继承方式的高阶组件,所以优先使用代理方式的高阶组件。
三、修改显示的组件名
打开组件调试工具,可以看到组件B和组件C重名了,都是A,如果组件特别多的话,调试起来会很麻烦。
image.png
修改方法
这时候需要用到 react 类里面的静态属性 displayName,用于设置显示的组件名称。
A.js
import React, { Component } from 'react';
function hocA(Wrapper) {
  return class A extends Component {
    // 设置显示高阶组件显示名称
    static displayName = `Box${getDisplayName(Wrapper)}`;
    render() {
      return (
        
发表评论 (审核通过后显示评论):