高階函數HOF和高階組件HOC(Higher Order Func/Comp)

1、什麼是高階函數(組件),做用是什麼?

子類使用父類的方法能夠經過繼承的方式實現,那無關聯組件通訊(redux)、父類使用子類方法(反向繼承)呢
爲了解決類(函數)功能交叉/功能複用等問題,經過傳入類/函數返回類/函數(繼承)的方式使得類擁有自身未定義的方法。html

例如react-redux的connect方法使用了高階組件:react

React Redux的connect:redux

const HOC = connnect(mapStateToProps)(Comp);
// connect爲柯里化函數  實際爲 =>
function connect(mapStateToProps) {
  // ...
  return function(Comp) {
    // ...
  }
}
// 使用箭頭函數則爲
const connect = mapStateToProps => Comp => {...};

2、經過高階函數實現兩個無關函數的通訊

需求介紹

存在一個類SubClass(子類),該類範圍內有數據state對象,且有setState和getState兩個函數方法。如今但願經過SupClass1(超/父類1)去調用SubClass(子類)的setState方法,並在SupClass2(超/父類2)裏經過getState方法輸出結果。數組

注意,子爲sub,父爲sup函數

文件目錄
├  ├── SubClass.js              # 子類
├  ├── SupClass1.js             # 父類1
├  ├── SupClass2.js             # 父類2
├── index.html

SubClass類增長數據state,並賦予查詢修改的能力this

// SubClass.js
class SubClass {
  constructor(args = {}) {
    this.state = {
      ...args,
    };
  }
  // 賦值時須要提供鍵和值
  setState = (key, val) => {
    this.state = {
      [key]: val,
    };
  };
  getState = (key) => {
    if (key in this.state) {
      return this.state[key];
    }
    // 固然咱們但願嚴謹點
    const err = '無效key值';
    throw err;
  };
}

咱們試試SubClass功能如何code

// index.html
const subcls = new SubClass({name: 'xiaobe'});
const res = subCls.getState('name');
console.log('res', res);
// 輸出xiaobe,妥妥的

接下來咱們給SupClass1賦予setState的能力htm

class SuperClass1 {
  set(key, val) {
    // SuperClass1裏沒有setState方法!
    this.setState(key, val);
  }
}

若是直接執行類裏的get方法確定是會出錯的。因此咱們須要先對SupClass1作點事情。對象

須要給SuperClass1類裏增長方法setState,可使用繼承繼承

// SuperClass1.js
class SuperClass1 extends SubClass {
  constructor(props) {
    super(props);
  }
  set(key, val) {
    // 父類1上使用子類的setState方法
    this.setState(key, val);
  }
}

// index.html
const supCls1 = new SuperClass1({name: 'sup-xiaobe'});
const res = supCls1.getState('name');
console.log(res);
// 也能輸出sup-xiaobe

但若是單純使用繼承的方式會形成不少的麻煩,試想下若是兩個非父子關係的組件使用了繼承,會致使自身的方法被覆蓋掉!

所以咱們仍是須要經過高階組件實現;

首先咱們先給子類SubClass增長一個HOC入口

class SubClass {
  // ...
  HOC(cls) {
    // 須要調用SubClass類的方法,因此須要存一份其this
    const sub_this = this;
    // 父類除了如下新增的兩個方法,其餘無任何變化地返回!
    return class extends cls {
      constructor(props) {
        super(props);
        // 此處this指向該子類,sub_this指向SubClass類
        this.getState = sub_this.getState;
        this.setState = sub_this.setState;
      }
    }
  }
  // ...
}

接着咱們來父類1SupClass1實例化前升級(調用HOC)!

// index.html
const subCls = new SubClass();
// 在子類實例化後給父類加上HOC方法
const supClsHoc1 = subCls.HOC(SuperClass1);
// 實例化父類
const supCls1 = new supClsHoc1();
// 從新定義state.name
supCls1.set('name', 'sup-xiaobe');

console.log(supCls.getState('name'));
// 輸出sup-xiaobe

同理地完成SupClass2

// SupClass2.js
class SuperClass2 {
  get(key) {
    return this.getState(key);
  }
}

// 最終的index.html
const subCls = new SubClass({name: 'xiaobe'});
const supClsHoc1 = subCls.HOC(SuperClass1);
const supClsHoc2 = subCls.HOC(SuperClass2);
const supCls1 = new supClsHoc1();
const supCls2 = new supClsHoc2(); 

supCls1.set('name', 'sup-xiaobe');
const res = supCls2.get('name');
console.log('res', res);

這麼一個基礎簡單的組件通訊就完成了。

根據這個思路能夠封裝一個相似全局變量的Store.js

--- 後面介紹

React HOC

相關文章
相關標籤/搜索