高階元件的定義
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),碼上獲取更多優質乾貨!