高階組件&&高階函數(一)


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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM