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,關閉按鈕其他的就可以做為上面說的基本材料。
高階組件總共分為兩大類
- 代理方式
- 操縱prop
- 訪問ref(不推薦)
- 抽取狀態
- 包裝組件
- 繼承方式
- 操縱生命周期
- 操縱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
