今天有幸去參加了下別人公司的分享會,我帶着想讓我的給我梳理下我對高階組件瞭解比較混亂的思路,但分享的內容跟我指望方向不在一個點上,因此結束後我仍是想象,我本身來梳理下本身對高階組件淺顯的理解。但願你們給予指導react
要講高階組件,先讓我介紹下高階函數,這樣類比下就很容易理解了。git
高階函數:以函數做爲參數的函數,結果return一個函數。
(感謝有人指出錯誤,高階函數只要知足參數或返回值爲函數就能夠成爲高階函數,而非必定要同時知足才成立)
高階組件:以組件做爲參數的組件,結果return一個組件。github
高階函數(Higher Order Function),按照維基百科上面的定義,至少知足下列一個條件的函數web
簡單的例子:redux
function add(a,b,fn){
return fn(a)+fn(b);
}
var fn=function (a){
return a*a;
}
add(2,3,fn); //13
複製代碼
還有一些咱們平時經常使用高階的方法,如: Map、Reduce、Filter、Sort;
以及如今經常使用的redux中的connect方法也是高階函數。
注:一開始我都不知道這幾個經常使用的方法竟然就是高階函數,拿map展現下app
var pow = function square(x) {
return x * x;
};
var array = [1, 2, 3, 4, 5, 6, 7, 8];
var newArr = array.map(pow); //直接傳入一個函數方法
var newArr = array.map((item) => {return item * item}); //裏面運用一個函數
//返回的一個函數
alert(newArr); // [1, 4, 9, 16, 25, 36, 49, 64]
複製代碼
在計算機科學中,柯里化(英語:Currying),又譯爲卡瑞化或加里化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數並且返回結果的新函數的技術。wordpress
對個人的理解就是函數裏面的函數分次傳進去,我本身寫了個很是簡單的例子。函數
var add = function(x) {
return function(y) {
return function(z){
console.log('curr',x,y,z)
return x+y+z;
};
};
};
console.log(add(1)(5)(5));//傳三個參數
///currying 1 5 5
//11
console.log(add(1)(5));//若是傳兩個參數,則會把第三個函數返回出來
/*ƒ (z) { console.log('currying', x, y, z); return x + y + z; } */
//若是多傳則會報錯
複製代碼
因此,我對柯里化的運用場景仍是比較少的。 不知爲什麼, 我以爲上面那個栗子有點奇怪,因此,我又試了下面這個栗子,能夠無限傳參;ui
var add = function(action) {
var sumFun = function(doing){
var sum = '';
if(action == 'sum'){
console.log('befor',sum)
if(doing){
sum = doing;
}else{
sum = 'nothing'
}
}
console.log('lastSum='+sum);
return sumFun ;
}
return sumFun ;
};
add('sum')(2)(3)();//2 3 nothing;
add('sum')(2)(3)(4)(5);// 2 3 4 5
複製代碼
ES6的中的寫法其實會比較清晰this
var add2 = x => y => x+y;
var add3 = add2(2)
console.log('add2',add2(2)) //返回一個方法,不調用後面的函數
console.log('add3',add3(5)) //7
// 分步傳參,第二次調用時纔會去執行函數。
複製代碼
總結(個人理解):柯里化函數就是一種分步傳參的函數,能夠提早傳參而不讓他執行內容,可是參數知足時再調用函數。感受能夠用來作一些未知的判斷。
高階組件就是一個 React 組件包裹着另一個 React 組件。
// It's a function...
function myHOC() {
// Which returns a function that takes a component...
return function(WrappedComponent) {
// It creates a new wrapper component...
class TheHOC extends React.Component {
render() {
// And it renders the component it was given
return <WrappedComponent {...this.props} />; } } // Remember: it takes a component and returns a new component // Gotta return it here. return TheHOC; } } 複製代碼
如圖,高階組件是個純函數。 接受一個組件參數,而後在return裏面是返回一個組件。 用來把兩個相似的組件進行'封裝'?(不知用這個詞是否合適)而後在高階組件裏面把公共部分寫好,而後傳給組件。
來個好理解的例子吧
//Welcome 組件
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;
複製代碼
//goodbye 組件
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;
複製代碼
從上述可見, 這兩個組件雖然功能不同, 可是兩個組件有許多同樣的代碼,這樣感受就很是的多餘。因此,咱們就能夠作一個高階組件來整合。
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組件
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;
//高階的goodbye組件
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;
複製代碼
一、官方推薦在高階組件裏儘可能不要設置state值,傳值的話能夠用props的方法。 二、儘可能不去改變原始組件,而是經過組合的方式。
提供參考的博文地址: JS中的柯里化(currying)-張鑫旭
React高階組件(譯)
助你徹底理解React高階組件