原文地址:https://github.com/brickspert... (若是你以爲對你有幫助,請在github給個star~您的start是我不斷創做的動力!)
原文不斷更新,此處不維護。javascript
有時候人們很喜歡造一些名字很嚇人的名詞,讓人一聽這個名詞就以爲本身不可能學會,從而讓人望而卻步。可是其實這些名詞背後所表明的東西其實很簡單。來自React.js 小書css
a higher-order component is a function that takes a component and returns a new component.html
翻譯:高階組件就是一個函數,且該函數接受一個組件做爲參數,並返回一個新的組件。java
理解了嗎?看了定義似懂非懂?繼續往下看。react
咱們經過普通函數來理解什麼是高階組件哦~git
最普通的方法,一個welcome
,一個goodbye
。兩個函數先從localStorage
讀取了username
,而後對username
作了一些處理。github
function welcome() { let username = localStorage.getItem('username'); console.log('welcome ' + username); } function goodbey() { let username = localStorage.getItem('username'); console.log('goodbey ' + username); } welcome(); goodbey();
咱們發現兩個函數有一句代碼是同樣的,這叫冗餘唉。很差很差~(你能夠把那一句代碼理解成平時的一大堆代碼)redux
咱們要寫一箇中間函數,讀取`username`,他來負責把`username`傳遞給兩個函數。
function welcome(username) { console.log('welcome ' + username); } function goodbey(username) { console.log('goodbey ' + username); } function wrapWithUsername(wrappedFunc) { let newFunc = () => { let username = localStorage.getItem('username'); wrappedFunc(username); }; return newFunc; } welcome = wrapWithUsername(welcome); goodbey = wrapWithUsername(goodbey); welcome(); welcome();
好了,咱們裏面的wrapWithUsername
函數就是一個「高階函數」。
他作了什麼?他幫咱們處理了username
,傳遞給目標函數。咱們調用最終的函數welcome
的時候,根本不用關心username
是怎麼來的。antd
咱們增長個用戶study
函數。app
function study(username){ console.log(username+' study'); } study = wrapWithUsername(study); study();
這裏你是否是理解了爲何說wrapWithUsername
是高階函數?咱們只須要知道,用wrapWithUsername
包裝咱們的study
函數後,study
函數第一個參數是username
。
咱們寫平時寫代碼的時候,不用關心wrapWithUsername
內部是如何實現的。
高階組件就是一個沒有反作用的純函數。
咱們把上一節的函數通通改爲react
組件。
最普通的組件哦。
welcome
函數轉爲react
組件。
import React, {Component} from 'react' class Welcome extends Component { constructor(props) { super(props); this.state = { username: '' } } componentWillMount() { let username = localStorage.getItem('username'); this.setState({ username: username }) } render() { return ( <div>welcome {this.state.username}</div> ) } } export default Welcome;
goodbey
函數轉爲react
組件。
import React, {Component} from 'react' class Goodbye extends Component { constructor(props) { super(props); this.state = { username: '' } } componentWillMount() { let username = localStorage.getItem('username'); this.setState({ username: username }) } render() { return ( <div>goodbye {this.state.username}</div> ) } } export default Goodbye;
如今你是否是更能看到問題所在了?兩個組件大部分代碼都是重複的唉。
按照上一節wrapWithUsername
函數的思路,咱們來寫一個高階組件(高階組件就是一個函數,且該函數接受一個組件做爲參數,並返回一個新的組件)。
import React, {Component} from 'react' export default (WrappedComponent) => { class NewComponent extends Component { constructor() { super(); this.state = { username: '' } } componentWillMount() { let username = localStorage.getItem('username'); this.setState({ username: username }) } render() { return <WrappedComponent username={this.state.username}/> } } return NewComponent }
這樣咱們就能簡化Welcome
組件和Goodbye
組件。
import React, {Component} from 'react'; import wrapWithUsername from 'wrapWithUsername'; class Welcome extends Component { render() { return ( <div>welcome {this.props.username}</div> ) } } Welcome = wrapWithUsername(Welcome); export default Welcome;
import React, {Component} from 'react'; import wrapWithUsername from 'wrapWithUsername'; class Goodbye extends Component { render() { return ( <div>goodbye {this.props.username}</div> ) } } Goodbye = wrapWithUsername(Goodbye); export default Goodbye;
看到沒有,高階組件就是把username
經過props
傳遞給目標組件了。目標組件只管從props
裏面拿來用就行了。
到這裏位置,高階組件就講完了。你再返回去理解下定義,是否是豁然開朗~
你如今理解react-redux
的connect
函數~
把redux
的state
和action
建立函數,經過props
注入給了Component
。
你在目標組件Component
裏面能夠直接用this.props
去調用redux state
和action
建立函數了。
ConnectedComment = connect(mapStateToProps, mapDispatchToProps)(Component);
至關於這樣
// connect是一個返回函數的函數(就是個高階函數) const enhance = connect(mapStateToProps, mapDispatchToProps); // 返回的函數就是一個高階組件,該高階組件返回一個與Redux store // 關聯起來的新組件 const ConnectedComment = enhance(Component);
antd
的Form也是同樣的
const WrappedNormalLoginForm = Form.create()(NormalLoginForm);
參考地址: