React 高階元件介紹

創宇前端發表於2019-03-04

高階元件的定義

HoC 不屬於 React 的 API,它是一種實現模式,本質上是一個函式,接受一個或多個 React 元件作為引數,返回一個全新的 React 元件,而不是改造現有的元件,這樣的元件被稱為高階元件。開發過程中,有的功能需要在多個元件類複用時,這時可以建立一個 Hoc。

基本用法

  • 包裹方式
const HoC = (WrappendComponent) => {
    const WrappingComponent = (props) => (
        <div className="container">
            <WrappendComponent {...props} />
        </div>
    );
    return WrappingComponent;
};
複製程式碼

上述程式碼中,接受 WrappendComponent 作為引數,此引數就是將要被 HoC 包裝的普通元件,在 render 中包裹一個 div,賦予它 className 屬性,最終產生的 WrappingComponent 和 傳入的 WrappendComponent 是兩個完全不同的元件。

在 WrappingComponent 中,可以讀取、新增、編輯、刪除傳給 WrappendComponent 的 props,也可以用其它元素包裹 WrappendComponent,用來實現封裝樣式、新增布局或其它操作。

  • 組合方式
const HoC = (WrappedComponent, LoginView) => {
    const WrappingComponent = () => {
        const {user} = this.props;  
        if (user) {
            return <WrappedComponent {...this.props} />
        } else {
            return <LoginView {...this.props} />
        }
    };
    return WrappingComponent;
};
複製程式碼

上述程式碼中有兩個元件,WrappedComponent 和 LoginView,如果傳入的 props 中存在 user,則正常顯示的 WrappedComponent 元件,否則顯示 LoginView 元件,讓使用者去登入。HoC 傳遞的引數可以為多個,傳遞多個元件定製新元件的行為,例如使用者登入狀態下顯示主頁面,未登入顯示登入介面;在渲染列表時,傳入 List 和 Loading 元件,為新元件新增載入中的行為。

  • 繼承方式
const HoC = (WrappendComponent) => {
    class WrappingComponent extends WrappendComponent {
        render() (
            const {user, ...otherProps} = this.props;
            this.props = otherProps;
            return super.render();
        }
    }
    return WrappingComponent;
};
複製程式碼

WrappingComponent 是一個新元件,它繼承自 WrappendComponent,共享父級的函式和屬性。可以使用 super.render() 或者 super.componentWillUpdate() 呼叫父級的生命週期函式,但是這樣會讓兩個元件耦合在一起,降低元件的複用性。

React 中對元件的封裝是按照最小可用單元的思想來進行封裝的,理想情況下,一個元件只做一件事情,符合 OOP 中的單一職責原則。如果需要對元件的功能增強,通過組合的方式或者新增程式碼的方式對元件進行增強,而不是修改原有的程式碼。

注意事項

  • 不要在 render 函式中使用高階元件
render() {
  // 每一次render函式呼叫都會建立一個新的EnhancedComponent例項
  // EnhancedComponent1 !== EnhancedComponent2
  const EnhancedComponent = enhance(MyComponent);
  // 每一次都會使子物件樹完全被解除安裝或移除
  return <EnhancedComponent />;
}
複製程式碼

React 中的 diff 演算法會比較新舊子物件樹,確定是否更新現有的子物件樹或丟掉現有的子樹並重新掛載。

  • 必須將靜態方法做拷貝
// 定義靜態方法
WrappedComponent.staticMethod = function() {/*...*/}
// 使用高階元件
const EnhancedComponent = enhance(WrappedComponent);

// 增強型元件沒有靜態方法
typeof EnhancedComponent.staticMethod === `undefined` // true
複製程式碼
  • Refs屬性不能傳遞

HoC中指定的 ref,並不會傳遞到子元件,需要通過回撥函式使用 props 傳遞。

參考連結


關注微信公眾號:創宇前端(KnownsecFED),碼上獲取更多優質乾貨!

React 高階元件介紹

相關文章