美文网首页React
01-react-高阶函数HOC

01-react-高阶函数HOC

作者: 低头看云 | 来源:发表于2020-10-12 10:43 被阅读0次

    高阶函数(HOC)

    为了提高组件复用率,可测试性,就要保证组件功能单⼀性;
    但是若要满⾜复杂需求就要扩展功能单⼀的组件,在React里就有了HOC(Higher-Order Components)的概念。

    定义: ⾼阶组件是参数为组件,返回值为新组件的函数
    最为出名的就是 redux 中的 connect函数

    // hoc.js
    
    import React from 'react'
    
    /**
    
    高阶组件-HOC
    为了了提高组件复用率,可测试性,就要保证组件功能单一性;但是
    若要满足复杂需求就要扩展功能单一的组件,在React里就有了
    HOC(Higher-Order Components)的概念。
    定义: ⾼高组件是参数为组件,返回值为新组件的函数
    最为出名的就是 redux 中的 connect函数
    
     */
    // foo函数 接受一个函数, 返回新的组件
    // Com 这里是指 function 或者 class组件
    const foo = (Com) => (props) => {
      return (
        <div className="red-bd">
          <Com {...props}></Com>
        </div>
      )
    }
    
    const foo2 = (Com) => (props) => {
      return (
        <div className="blue-bd">
          <Com {...props}></Com>
        </div>
      )
    }
    
    // 其他写法
    //  higherOrderComponent 接受了一个组件 wrappedComponent
    const higherOrderComponent = (wrappedComponent)=>{
        // 做些逻辑判断可以返回其他函数
        class HOC extends React.Component {
            render(){
                return <WrappedComponent />
            }
        }
        
        // 返回一个新的组件
        return HOC
    }
    
    
    function Child(props) {
      return <div>我是Child {props.name}</div>
    }
    
    export default foo2(foo(Child))
    
    
    
    // app.css
    .red-bd {
      border: 1px solid #f00;
      padding: 5px;
    }
    
    .blue-bd {
      border: 1px solid #00f;
      padding: 5px;
    }
    
    
    // app.js
    import React from 'react'
    import Hoc from './views/Hoc'
    import './App.css'
     function App() {
      return (
        <div className="App">
          <Hoc name="test" />
        </div>
      )
    }
    
    export default App
    
    • 效果如下图
    image-20201010152437778

    装饰器写法

    高阶组件本身是对装饰器器模式的应⽤用,自然可以利用ES7中出现的装饰器语法来更优雅的书写代码。

    yarn add customize-cra react-app-rewired --dev
    yarn add  @babel/plugin-proposal-decorators --dev
    

    更新 config-overrides.js

    // config-overrides.js
    //配置完成后记得重启下
    const { override, addDecoratorsLegacy } = require('customize-cra')
    
    module.exports = override(
      addDecoratorsLegacy() //配置装饰器器
    )
    
    // 同时还要修改 package.json
    
      "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eject": "react-app-rewired eject"
      },
    

    装饰器写法修改 Child组件

    // 装饰器写法
    // 装饰器只能用在class组件上
    // 执行顺序从下往上
    @foo2
    @foo
    class Child1 extends Component {
      render() {
        return <div>我是装饰器写法 {this.props.name}</div>
      }
    }
    
    export default Child1
    

    使用HOC的注意事项

    不要在render方法中使用HOC

    React 的 diff 算法(称为协调)使⽤组件标识来确定它是应该更新现有子树还是将其丢弃并挂载新子树。 如果从 render 返回的组件与前一个渲染中的组件相同( ===),则 React 通过将⼦树与新子树进行区分来递归更新子树。 如果它们不相等,则完全卸载前一个子树 。

    render() {
        // 每次调⽤用 render 函数都会创建⼀一个新的
        EnhancedComponent
        // EnhancedComponent1 !== EnhancedComponent2
        const EnhancedComponent = enhance(MyComponent);
        // 这将导致⼦子树每次渲染都会进⾏行行卸载,和重新挂载的操作!
        return <EnhancedComponent />;
    }
    

    不仅仅是性能问题 - 重新挂载组件会导致该组件及其所有子组件的状态丢失

    相关文章

      网友评论

        本文标题:01-react-高阶函数HOC

        本文链接:https://www.haomeiwen.com/subject/ulsupktx.html