高階組件是什麼東西 簡單的理解是:一個包裝了另一個基礎組件的組件。(相對高階組件來說,我習慣把被包裝的組件稱為基礎組件) 註意:這裡說的是包裝,可以理解成包裹和組裝; 具體的是高階組件的兩種形式吧: a、屬性代理(Props Proxy) 可以說是對組件的包裹,在包裹的過程中對被包裹的組件做了點什麼 ...
高階組件是什麼東西
簡單的理解是:一個包裝了另一個基礎組件的組件。(相對高階組件來說,我習慣把被包裝的組件稱為基礎組件)
註意:這裡說的是包裝,可以理解成包裹和組裝;
具體的是高階組件的兩種形式吧:
a、屬性代理(Props Proxy)
可以說是對組件的包裹,在包裹的過程中對被包裹的組件做了點什麼(props的處理,把基礎組件和其他元素組合),然後返回,這就成了一個高階組件;
b、反向繼承 (Inheritance Inversion)
可以理解成是組裝,和屬性代理不同的是,反向繼承是繼承自基礎組件,所有很自然,它可以直接獲取基礎組件的props,操作基礎組件的state。可以通過 反向繼承的形式,配合compose將攜帶不同功能模塊的高階組件組裝到基礎組件上,加強基礎組件。
本文慄子:https://github.com/wayaha/react-demos-HOC
compose慄子:https://github.com/wayaha/react-dom-compose
(如果對您有幫助,請幫我點顆star)
下邊一個一個的說。
屬性代理(Props Proxy)
我們可以先建一個基礎組件,如下:
class BaseComponent extends Component { constructor (props) { super(props); this.state = { baseName: 'base component' }; };render () { const { name} = this.props; const { baseName } = this.state; return <div>{`${name} + ${baseName}`}</div> }; };
為了便於說明問題,寫一個很簡答的基礎組件,它的作用僅僅是返回一個div,顯示他自己的名字;
a、對props的操作
這個高階組件是一個相對簡單的無狀態組件,只是這個高階組件返回了一個新的組件,而這個新的組件是對基礎組件的一個包裝。僅僅對基礎組件的props進行了增加,當然也可以進行改變,刪除和讀取(具體的可以下載代碼上手試試)。
註意:(1)、此時render方法內的this.props,它是InnerComponent組建的props,而BaseComponent組件實際也就是InnerComponent組件。
(2)、高階組件中的InnerComponent組件是一個完整的組件,可以根據需要添加一下state狀態,作為props傳到BaseComponent組件。可以將基礎組件作為一個公共的組件,然後根據需要,使用的不同的高階組件包裝出具有不一樣功能的組件。
import React, { Component } from 'react';const PropsComponent = (BaseComponent) => {
class InnerComponent extends Component { render () { const props = { ...this.props, name: 'HOC Component' }; return <BaseComponent {...props} /> }; };
return InnerComponent; } export default PropsComponent;
b、把基礎組件和其他元素組合
出於操作樣式、佈局或其它的考慮,可以將 基礎組件與其它組件包裹在一起。一些相對簡單的用法也可以使用正常的父組件來實現,只是使用高階組件可以獲得更多的靈活性。也利於組件的抽象和復用。
const WrapperComponent = (BaseComponent) => { class InnerComponent extends Component { render () { const props = { ...this.props, name: 'HOC Component' }; return <div style={{backgroundColor: 'orange'}}> <BaseComponent {...props} /> </div> }; }; return InnerComponent; }
反向繼承(Inheritance Inversion)
反向繼承是繼承自基礎組件,並不是高階組件繼承傳入的基礎組件,所以成為反向繼承。由於高階組件繼承了基礎組件,那麼高階組件通過this可以操作基礎組件的state,props以及基礎組件的方法,甚至可以通過super來操作基礎組件的生命周期。
a、渲染劫持
所謂渲染劫持就是,高階組件控制了基礎組件渲染生成的結果,因為基礎組件的渲染被控制,高階組件就可以對它做點什麼。。。比如:
(1)、看心情(根據條件),控制渲染的結果;
(2)、改變dom樹的樣式;
(3)、改變基礎組件中一下被渲染元素的props;
(4)、操作dom樹中的元素。
這個就是根據props傳入的條件來決定要不要渲染。
const HOCComponent = (BaseComponent) => { return class Enhancer extends BaseComponent{ render() { if (this.props.loggedIn) { return super.render() } else { return null } } } }
通過super.render()獲取基礎組件的dom樹,然後就可以進行一些操作,改變dom樹的樣式,改變基礎組件中一下被渲染元素的props,操作dom樹中的元素等等。
HOCComponent = (BaseComponent) => { return class Enhancer extends BaseComponent { render() { const domsTree = super.render() let newProps = {}; if (domsTree && domsTree.type === 'input') { newProps = {value: 'this is new value'} } const props = Object.assign({}, domsTree.props, newProps) const newDomsTree = React.cloneElement(domsTree, props, domsTree.props.children) return newDomsTree } } }
b、操作state
高階組件可以讀取、編輯和刪除 基礎組件 實例的 state,如果你需要,你也可以給它添加更多的 state。需要註意的是,這會搞亂基礎組件 的 state,導致你可能會破壞某些東西。所以,要限制高階組件讀取或添加 state,添加 state 時應該放在單獨的命名空間里,而不是和基礎組件的 state 混在一起。
另外,高階組件配合compose實現功能模塊化,和個功能模塊的隨意組合使用。(見上文github例子)
每一個高階組件封裝一種功能,例如例子中的AddStaff,ChangeStaffData,DeleteStaff,ShowStaffMsg,可以根據需要將高階組件組合到任意的基礎組件中,實現功能模塊化,也方便代碼的抽離和復用。