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
  • 相关阅读:
    Linux实时性分析-schedule-调度器
    中断解析
    网络商城-PrestaShop
    和学生的学习互动记录(10嵌)
    QQ记录
    Windows7硬盘安装Fedora16图文教程
    今目标登录时报网络错误E110
    vs环境配置——vs快捷键配置——vs插件配置——vs环境设置
    如何防止app接口被别人调用
    mvc4 找到多个与名为“xx”的控制器匹配的类型
  • 原文地址:https://www.cnblogs.com/tommymarc/p/12019970.html
Copyright © 2011-2022 走看看