高階組件就是一個 React 組件包裹着另一個 React 組件編程
高階組件的思路則是函數式的,每個擴展(Enhance)就是一個函數,接受要擴展的組件做爲參數。若是要進行 3 個擴展,那麼則能夠級聯,看起來就是:bootstrap
const newComponent = Enhance3(Enhance2(Enhance1(MyComponent)));
高階組件的方式則使得每個 Enhance 以及被擴展的組件都只關心本身手裏那點事。Enhance 不知作別人會怎麼用它,被擴展的組件也不關心別人會怎麼擴展它。負責人是那個將它們連在一塊兒的」水管工」,即最後寫串聯代碼的人。app
高階組件的用法雖然用到了 ES6 的類繼承,可是實際上卻只是把它當個工具使用,而不是真的藉助於 OO 的繼承。在 React 中使用高階組件部分替代 Mixins,仍然是很是函數化的思惟方式,即針對 」轉換」 編程。只不過是組件定義替代了函數而已。async
代碼複用,邏輯抽象,抽離底層準備(bootstrap)代碼函數
渲染劫持工具
State 抽象和更改fetch
Props 更改this
import { Component } from "React" ; export const Enhance = (ComposedComponent) => class extends Component { constructor() { this.state = { data: null }; } componentDidMount() { this.setState({ data: 'Hello' }); } render() { return <ComposedComponent {...this.props} data={this.state.data} />; } }; import { Component } from "React"; import { Enhance } from "./Enhance"; class MyComponent = class extends Component { render() { if (!this.props.data) return <div>Waiting...</div>; return <div>{this.data}</div>; } } export default Enhance(MyComponent); // Enhanced component`
Props Proxy 能夠作什麼:code
更改 propscomponent
經過 refs 獲取組件實例
抽象 state
把 WrappedComponent 與其它 elements 包裝在一塊兒
function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { const newProps = { user: currentLoggedInUser } return <WrappedComponent {...this.props} {...newProps}/> } } }
function refsHOC(WrappedComponent) { return class RefsHOC extends React.Component { proc(wrappedComponentInstance) { wrappedComponentInstance.method() } render() { const props = Object.assign({}, this.props, {ref: this.proc.bind(this)}) return <WrappedComponent {...props}/> } } }
function ppHOC(WrappedComponent) { return class PP extends React.Component { constructor(props) { super(props) this.state = { name: '' } this.onNameChange = this.onNameChange.bind(this) } onNameChange(event) { this.setState({ name: event.target.value }) } render() { const newProps = { name: { value: this.state.name, onChange: this.onNameChange } } return <WrappedComponent {...this.props} {...newProps}/> } } }
function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { return ( <div style={{display: 'block'}}> <WrappedComponent {...this.props}/> </div> ) } } }
能夠用反向繼承高階組件作什麼?
渲染劫持(Render Highjacking)
操做 state
它被叫作渲染劫持是由於高階組件控制了 WrappedComponent 生成的渲染結果,而且能夠作各類操做。
經過渲染劫持你能夠:
讀取、添加、修改、刪除』任何一個將被渲染的 React Element 的 props
在渲染方法中讀取或更改 React Elements tree,也就是 WrappedComponent 的 children
根據條件不一樣,選擇性的渲染子樹
給子樹裏的元素變動樣式
function iiHOC(WrappedComponent) { return class Enhancer extends WrappedComponent { render() { return super.render() } } } function iiHOC(WrappedComponent) { return class Enhancer extends WrappedComponent { render() { if (this.props.loggedIn) { return super.render() } else { return null } } } }
高階組件能夠 『讀取、修改、刪除』WrappedComponent 實例的 state,若是須要也能夠添加新的 state。須要記住的是,你在弄亂 WrappedComponent 的 state,可能會致使破壞一些東西。一般不建議使用高階組件來讀取或添加 state,添加 state 須要使用命名空間來防止與 WrappedComponent 的 state 衝突。
export function IIHOCDEBUGGER(WrappedComponent) { return class II extends WrappedComponent { render() { return ( <div> <h2>HOC Debugger Component</h2> <p>Props</p> <pre>{JSON.stringify(this.props, null, 2)}</pre> <p>State</p><pre>{JSON.stringify(this.state, null, 2)}</pre> {super.render()} </div> ) } } }
function hoc(ComponentClass) { return class HOC extends ComponentClass { render() { if (this.state.success) { return super.render() } return <div>Loading...</div> } } } @hoc export default class ComponentClass extends React.Component { state = { success: false, data: null }; async componentDidMount() { const result = await fetch(...請求); this.setState({ success: true, data: result.data }); } render() { return <div>主要內容</div> } }
從上面的例子能夠得出Higher-Order Components = Decorators + Components