從高階函數--->高階組件

前言

今天有幸去參加了下別人公司的分享會,我帶着想讓我的給我梳理下我對高階組件瞭解比較混亂的思路,但分享的內容跟我指望方向不在一個點上,因此結束後我仍是想象,我本身來梳理下本身對高階組件淺顯的理解。但願你們給予指導react

要講高階組件,先讓我介紹下高階函數,這樣類比下就很容易理解了。git

高階函數:以函數做爲參數的函數,結果return一個函數
(感謝有人指出錯誤,高階函數只要知足參數或返回值爲函數就能夠成爲高階函數,而非必定要同時知足才成立)
高階組件:以組件做爲參數的組件,結果return一個組件github

1、高階函數

高階函數(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
 
// 分步傳參,第二次調用時纔會去執行函數。
複製代碼

總結(個人理解):柯里化函數就是一種分步傳參的函數,能夠提早傳參而不讓他執行內容,可是參數知足時再調用函數。感受能夠用來作一些未知的判斷。

2、高階組件

高階組件就是一個 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高階組件

相關文章
相關標籤/搜索