Higher-order Components 高階組件

什麼是高階組件

高階組件就是一個 React 組件包裹着另一個 React 組件編程

高階組件的思路則是函數式的,每個擴展(Enhance)就是一個函數,接受要擴展的組件做爲參數。若是要進行 3 個擴展,那麼則能夠級聯,看起來就是:bootstrap

const newComponent = Enhance3(Enhance2(Enhance1(MyComponent)));

高階組件的方式則使得每個 Enhance 以及被擴展的組件都只關心本身手裏那點事。Enhance 不知作別人會怎麼用它,被擴展的組件也不關心別人會怎麼擴展它。負責人是那個將它們連在一塊兒的」水管工」,即最後寫串聯代碼的人。app

高階組件的用法雖然用到了 ES6 的類繼承,可是實際上卻只是把它當個工具使用,而不是真的藉助於 OO 的繼承。在 React 中使用高階組件部分替代 Mixins,仍然是很是函數化的思惟方式,即針對 」轉換」 編程。只不過是組件定義替代了函數而已。async

高階組件能夠作什麼

  1. 代碼複用,邏輯抽象,抽離底層準備(bootstrap)代碼函數

  2. 渲染劫持工具

  3. State 抽象和更改fetch

  4. 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: HOC 對傳給 WrappedComponent W 的 porps 進行操做

Props Proxy 能夠作什麼:code

  1. 更改 propscomponent

  2. 經過 refs 獲取組件實例

  3. 抽象 state

  4. 把 WrappedComponent 與其它 elements 包裝在一塊兒

更改 props

function ppHOC(WrappedComponent) {
      return class PP extends React.Component {
        render() {
             const newProps = {
            user: currentLoggedInUser
          }
          return <WrappedComponent {...this.props} {...newProps}/>
        }
      }
}

經過 refs 獲取組件實例

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}/>
        }    
      }
}

抽象 state

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}/>
    }
      }
}

把 WrappedComponent 與其它 elements 包裝在一塊兒

function ppHOC(WrappedComponent) {
      return class PP extends React.Component {
        render() {
             return (
                <div style={{display: 'block'}}>
                      <WrappedComponent {...this.props}/>
                </div>
              )
        }
      }
}

Inheritance Inversion: HOC 繼承 WrappedComponent W

能夠用反向繼承高階組件作什麼?

  1. 渲染劫持(Render Highjacking)

  2. 操做 state

渲染劫持

它被叫作渲染劫持是由於高階組件控制了 WrappedComponent 生成的渲染結果,而且能夠作各類操做。
經過渲染劫持你能夠:

  1. 讀取、添加、修改、刪除』任何一個將被渲染的 React Element 的 props

  2. 在渲染方法中讀取或更改 React Elements tree,也就是 WrappedComponent 的 children

  3. 根據條件不一樣,選擇性的渲染子樹

  4. 給子樹裏的元素變動樣式

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
              }
        }
      }
}

操做 state

高階組件能夠 『讀取、修改、刪除』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

相關文章
相關標籤/搜索