High Order Component(HOC) 高階組件

根據reactJs官方文檔的定義,HOC如下:
在這裏插入圖片描述
簡要來講的話,是一種重複利用組件邏輯的技術,接受一個組件,並且返回一個組件。
在這裏插入圖片描述
就上上面的例子一樣,會接受WrappedComponent然後返回enhancedComponent.下面舉例子來講解。

1.創建一個按鈕組件,並且監聽點擊次數

import React, { Component, useState, useEffect } from "react";

class ClickCounter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
    this.incrementCount = this.incrementCount.bind(this);
  }

  incrementCount() {
    this.setState(preveState => {
      return {
        count: preveState.count + 1
      };
    });
  }

  render() {
    let { count } = this.state;
    return (
      <div>
        <button onClick={this.incrementCount}>Clicked {count} times</button>
      </div>
    );
  }
}

export default ClickCounter;

以上按鈕組件我們創建了按鈕組件並且監聽了點擊事件,然後增加了被點擊的次數.

後來我們又接到了一個需求,是要做一個監聽hover次數的組件。

創建一個監聽Hover次數的組件

我們很快做出來了,其實我們做的過程中只是改了事件,其餘的從ClickCounter這裏複製粘貼了過來。

class HoverCounter extends Component {
  constructor() {
    super();
    this.state = {
      count: 0
    };
    this.incrementCount = this.incrementCount.bind(this);
  }

  incrementCount() {
    this.setState(preveState => {
      return {
        count: preveState.count + 1
      };
    });
  }

  render() {
    let { count } = this.state;
    return (
      <div>
        <h2 onMouseOver={this.incrementCount}>Hovered {count} times</h2>
      </div>
    );
  }
}

然後我們做完了以後,又來了一個需求,說要寫一個監聽input有多少次keypressed.這個時候我們想到的第一個辦法,就複製粘貼上面寫的兩個組件的方法,改一改事件監聽函數,但我們聰明起來了,我們想到寫一個父組件,然後把count和incrementCount方法通過props的方式傳下來到ClickCounter,HoverCounter組件.比如一下:
在這裏插入圖片描述
這樣可以解決問題,在我們這個場景可以解決問題,但如果是一下情況就不太行了 。

在這裏插入圖片描述
把邏輯代碼移到最上層的組件,不是一個好的解決方式。這個時候HOC閃亮登場了,它的作用就是在組件間分享重用的邏輯代碼,接受一個組件,並且返回一個增強的組件。

我們定義一個WithCounter組件,作爲HOC

import React, { Component, useState, useEffect } from "react";

const UpdatedComponent = OriginalComponent => {
  class NewComponent extends Component {
    render() {
      return <OriginalComponent name="Abdulla" />;
    }
  }

  return NewComponent;
};

export default UpdatedComponent;

可以看到我們實現了一個組件,這個組件接受名字叫originalComponent的組件,然後返回newComponent組件。
我們在這裏爲了演示在originalComponent那裏傳了一個props,爲name=“Abdulla”。
下面來看ClickCounter,HoverCounter組件有了什麼變化.
在這裏插入圖片描述
我們可以看到兩處有了變化,import和export那裏有了變化。然後可以看到我們通過this.props.name來使用了剛纔傳進來的props.
在HoverCounter組件也類似,可以看到起了作用.
在這裏插入圖片描述

把count和incrementCount邏輯放到HOC組件裏。

1.)我們首先把在ClickCounter和HoverCounter裏的count和incrementCount邏輯移出去。
2.)在WithCounter(HOC組件)裏寫count和incrementCount邏輯,然後通過props傳出去,就像我們傳name一樣。
3.)然後在ClickCounter和HoverCounter組件裏使用這個props.
最後展示一下這3個組件的代碼
ClickCounter組件:

import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";

class ClickCounter extends Component {
  constructor() {
    super();
    // this.state = {
    //   count: 0
    // };
    // this.incrementCount = this.incrementCount.bind(this);
  }

  //   incrementCount() {
  //     this.setState(preveState => {
  //       return {
  //         count: preveState.count + 1
  //       };
  //     });
  //   }

  render() {
    // let { count } = this.state;
    return (
      <div>
        <button onClick={this.props.incrementCount}>
          {this.props.name} Clicked {this.props.count} times
        </button>
      </div>
    );
  }
}

export default UpdatedComponent(ClickCounter);

沒有刪掉count和incrementCount邏輯,只是註釋了,爲了展示的更好,顯示HOC組件的優越性。

HoverCounter組件如下:

import React, { Component, useState, useEffect } from "react";
import UpdatedComponent from "./WithCounter";

class HoverCounter extends Component {
  constructor() {
    super();
    // this.state = {
    //   count: 0
    // };
    // this.incrementCount = this.incrementCount.bind(this);
  }

  //   incrementCount() {
  //     this.setState(preveState => {
  //       return {
  //         count: preveState.count + 1
  //       };
  //     });
  //   }

  render() {
    // let { count } = this.state;
    return (
      <div>
        <h2 onMouseOver={this.props.incrementCount}>
          {this.props.name} Hovered {this.props.count} times
        </h2>
      </div>
    );
  }
}

export default UpdatedComponent(HoverCounter);

WithCounter組件如下:

import React, { Component, useState, useEffect } from "react";

const UpdatedComponent = OriginalComponent => {
  class NewComponent extends Component {
    constructor() {
      super();
      this.state = {
        count: 0
      };
      this.incrementCount = this.incrementCount.bind(this);
    }

    incrementCount() {
      this.setState(preveState => {
        return {
          count: preveState.count + 1
        };
      });
    }

    render() {
      return (
        <OriginalComponent
          name="Abdulla"
          count={this.state.count}
          incrementCount={this.incrementCount}
        />
      );
    }
  }

  return NewComponent;
};

export default UpdatedComponent;

總結起來,HOC的作用是爲了精簡代碼,實現代碼的複用.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章