zoukankan      html  css  js  c++  java
  • 高阶组件&&高阶函数(一)

    antd里面的form表单方面,遇到一个高阶函数,以及高阶组件,于是看了一下这方面内容,前辈们的文章写得也非常详细,这里就稍微kobe一下

    高阶函数与高阶组件

    高阶函数:

    高阶函数,是一种特别的函数,接受的参数为函数,返回值也是函数

    成立条件,二者兼一即可

        1).一类特别的函数
            a).接受函数类型的参数
            b).函数返回值是函数

    常见的高阶函数:

        2).常见
            a).定时器:setTimeout()/setInterval()
            b).Promise:Promise(()=>{})  then(value=>{},reason=>{})
            c).数组遍历相关的方法: forEach()/ filter()/ map()/ find()/ findindex()
            d).fn.bind() 本身是个函数,bind方法返回一个新的函数方法
            e).Form.create()()  create函数能够包装组件,生成另外一个组件的新功能函数 
            f).getFieldDecorator()()
    1)函数作为参数的高阶函数
     setTimeout(()=>{
       console.log("aaaa")
      },1000)
    //2 函数作为返回值输出的高阶函数
      function foo(x){
            return function(){
               return x
            }
          }
    
     //平时遇到的应用场景      
    //ajax中
     $.get("/api",function(){
         console.log("获取成功")
      })
    
     //数组中
     some(), every(),filter(), map()和forEach() 

    高阶组件

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

    2 高阶组件是一个函数,并不一个组件

    简单说:高阶组件(函数)就好比一个加工厂,同样的配件、外壳、电池..工厂组装完成就是苹果手机,华为手机组装完成就是华为手机,基本材料都是相同,不同工厂(高阶组件)有不同的实现及产出。当然这个工厂(高阶组件)也可能是针对某个基本材料的处理,总之产出的结果拥有了输入组件不具备的功能,输入的组件可以是一个组件的实例,也可以是一个组件类,还可以是一个无状态组件的函数

    解决什么问题?

    随着项目越来越复杂,开发过程中,多个组件需要某个功能,而且这个功能和页面并没有关系,所以也不能简单的抽取成一个新的组件,但是如果让同样的逻辑在各个组件里各自实现,无疑会导致重复的代码。比如页面有三种弹窗一个有title,一个没有,一个又有右上角关闭按钮,除此之外别无它样,你总不能整好几个弹窗组件吧,这里除了tilte,关闭按钮其他的就可以做为上面说的基本材料。

    高阶组件总共分为两大类

    • 代理方式
      1. 操纵prop
      2. 访问ref(不推荐)
      3. 抽取状态
      4. 包装组件
    • 继承方式
      1. 操纵生命周期
      2. 操纵prop

     

    代理方式之 操纵prop

    删除prop
    import React from 'react'
    function HocRemoveProp(WrappedComponent) {
      return class WrappingComPonent extends React.Component {
        render() {
          const { user, ...otherProps } = this.props;
          return <WrappedComponent {...otherProps} />
        }
      }
    }
    export default HocRemoveProp;

    增加prop

    import React from 'react'
    
    const HocAddProp = (WrappedComponent,uid) =>
      class extends React.Component {
        render() {
          const newProps = {
            uid,
          };
          return <WrappedComponent {...this.props}  {...newProps}  />
        }
      }
    
    export default HocAddProp;

    上面HocRemoveProp高阶组件中,所做的事情和输入组件WrappedComponent功能一样,只是忽略了名为user的prop。也就是说,如果WrappedComponent能处理名为user的prop,这个高阶组件返回的组件则完全无视这个prop。

    const { user, ...otherProps } = this.props;

    这是一个利用es6语法技巧,经过上面的语句,otherProps里面就有this.props中所有的字段除了user.
    假如我们现在不希望某个组件接收user的prop,那么我们就不要直接使用这个组件,而是把这个组件作为参数传递给HocRemoveProp,然后我们把这个函数的返回结果当作组件来使用
    两个高阶组件的使用方法:

    const  newComponent = HocRemoveProp(SampleComponent);
    const  newComponent = HocAddProp(SampleComponent,'1111111');

    也可以利用decorator语法糖这样使用:

    import React, { Component } from 'React';
    
    @HocRemoveProp 
    class SampleComponent extends Component {
    render() {}
    }
    export default SampleComponent;
    //例子: A组件里面包含B组件
    
     import React , { Component }from 'react'
        function A(WrappedComponent){
         return  class A extends Component{  //这里必须retrun出去
           render() {
            return(
             <div>
               这是A组件
               <WrappedComponent></WrappedComponent>
             </div>
             )
           }
          }
         }
    
        export default  A

    高阶组件应用:

    //传参数
    
    import React, { Component } from 'react';
    import './App.css';
    import B from './components/B'
    class App extends Component {
      render() {
       return (
         <div className="App">
            这是我的APP
           <B age="18" name="Tom"/>
         </div>
       );
      }
    }
    export default App;
    
    
    //A组件
    import React , { Component }from 'react'
    export default (title)=> WrappedComponent => {
      return  class A extends Component{
       render() {
        return(
          <div>
             这是A组件{title}
             <WrappedComponent sex="男" {...this.props}></WrappedComponent>
          </div>
          )
         }
       }
     }
    
     //B组件
    import React , { Component }from 'react'
    import A from './A.js'
    class B extends Component{
      render() {
       return(
        <div>
         性别:{this.props.sex}
         年龄:{this.props.age}
         姓名:{this.props.name}
        </div>
       )
      }
     }
    export default  A('提示')(B)
    
    //有两种方式引用高阶函数,第一种入上
    //第二种
    
    import React , { Component }from 'react'
    import a from './A.js'
    @a('提示')
    class B extends Component{
      render() {
       return(
        <div>
         性别:{this.props.sex}
         年龄:{this.props.age}
         姓名:{this.props.name}
        </div>
       )
      }
     }
    export default B

    使用高阶组件

    1.higherOrderComponent(WrappedComponent);
    2.@higherOrderComponent

    高阶组件应用

    1.代理方式的高阶组件
        返回的新组件类直接继承自React.Component类,新组件扮演的角色传入参数组件的一个代理,
    在新组件的render函数中,将被包裹组件渲染出来,除了高阶组件自己要做的工作,其余功能全都转手给了被包裹的组件
    2.继承方式的高阶组件 采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent
    //代理方式的高阶组件
    export default ()=> WrappedComponent => 
        class A extends Component {
              render(){
                   const { ...otherProps } = this.props;
                   return <WrappedComponent {...otherProps} />  
        }             
    }
    
    //继承方式的高阶组件
    export default () => WrappedComponent => 
         class A extends WrappedComponent {
              render(){
                    const { use,...otherProps } = this.props;
                    this.props = otherProps;
                    return super.render()
         }
    }

    继承方式高阶组件的实现

       //D.js
    import React from 'react'
    const modifyPropsHOC= (WrappedComponent) =>  class NewComponent extends WrappedComponent{
    render() {
       const element = super.render();
       const newStyle = {
         color: element.type == 'div'?'red':'green'
       }
       const newProps = {...this.props,style:newStyle}
       return React.cloneElement(element,newProps,element.props.children)
     }
    } 
    export default modifyPropsHOC
    
    
     // E.js
    
    import React, {Component} from 'react'
    import D from './D'
    class E extends Component {
    render(){
    return (
      <div>
      我的div
      </div>
    );
    }
    }
    
    export default D(E)
    
    
    // F.js
    import React, {Component} from 'react'
    import d from './D'
    class F extends Component {
    render(){
    return (
      <p>
      我的p
      </p>
    );
    }
    }
    
    export default d(F)
    
    
    import React, { Component } from 'react';
    import './App.css';
    import E from './components/E'
    import F from './components/F'
    class App extends Component {
      render() {
    return (
      <div className="App">
       这是我的APP
       <E></E>
       <F></F>
      </div>
      );
      }
    }
    
    export default App;

    修改生命周期

    
    import React from 'react'
    const modifyPropsHOC= (WrappedComponent) =>  class NewComponent extends WrappedComponent{
    componentWillMount(){
    alert("我的修改后的生命周期");
    }
    render() {
       const element = super.render();
       const newStyle = {
    color: element.type == 'div'?'red':'green'
       }
       const newProps = {...this.props,style:newStyle}
       return React.cloneElement(element,newProps,element.props.children)
      }
    }
    
    export default modifyPropsHOC
  • 相关阅读:
    Atitit 人脸识别 眼睛形态 attilax总结
    Atitit 手机号码选号 规范 流程 attilax总结 v2 r99.docx
    atitit 板块分类 上市公司 龙头企业公司 列表 attilax总结.docx
    Atititi atiitt eam pam资产管理 购物表去年.xlsx
    使用cmd查看电脑连接过的wifi密码(一)
    常见十大web攻击手段 悟寰轩
    常见web攻击方式 悟寰轩
    【MYSQL数据库】MYSQL学习笔记mysql分区基本操作 悟寰轩
    Filter及FilterChain的使用详解 悟寰轩
    启动tomcat spring初始化两次问题(eg:@PostConstruct) 悟寰轩
  • 原文地址:https://www.cnblogs.com/tommymarc/p/12019970.html
Copyright © 2011-2022 走看看