React 學(xué)習(xí)筆記二 - HOC 高階組件理解

官方定義

高階組件(HOC)是 React 中用于<span style="color:red">復(fù)用組件邏輯</span>的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。

HOC 是單詞 Heigher Order Component 縮寫

具體而言,<span style="color:red">高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。

const EnhancedComponent = higherOrderComponent(WrappedComponent);

從官方定義中,我們可以抽取以下重點(diǎn):

  • 高階組件就是一個(gè)函數(shù).
  • 此函數(shù)接受一個(gè)組件作為參數(shù).
  • 此函數(shù)返回一個(gè)組件.
  • <span style="color:red"> 邏輯復(fù)用.或者說(shuō)組件的功能擴(kuò)展.

高階組價(jià),接受一個(gè)構(gòu)造函數(shù),返回一個(gè)構(gòu)造函數(shù). 所以,高階組件就是一個(gè)概念. 它本質(zhì)上也是高階函數(shù).

react-redux 里面的 connect 函數(shù),就是一個(gè)高階組件.

高級(jí)組件就是一個(gè)函數(shù),接受一個(gè)一個(gè)組件(函數(shù)),返回一個(gè)新組件(函數(shù))

理解高階組件.

既然高階組件,本質(zhì)上是一個(gè)函數(shù).那么我就給它一個(gè)組件作為入?yún)?在返回一個(gè)組件即可.

import React, { useState } from 'react'
import './App.css';
/**
 * 
 * 官方定義高階組件(HOC)是 React 中用于**復(fù)用組件邏輯**的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。
   HOC 是單詞 Heigher Order Component 縮寫
   具體而言,高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。
 * 
 * 
 */

function HelloComponent(props) {
  return (
    <div>
      <h2>我是一個(gè)定義的函數(shù)式組件 <span style={{ fontSize: '20px', color: '#f40' }}>{props.title}</span> </h2>
    </div>
  )
}

// 高階組件就是一個(gè)函數(shù),接收一個(gè)組件,返回一個(gè)[新]的組件.
const withComponent = (Component) => {
  return function WrapperComponent() {
    const [title, setTitle] = useState('這是由內(nèi)部組件 WrapperComponent 傳遞過來(lái)的 title')
    const changeTitle = () => {
      setTitle("這是新的 title")
    }
    return (
      <React.Fragment>
        <Component title={title} />
        <button onClick={changeTitle}>修改 title</button>
      </React.Fragment>
    )
  }
}

// 傳入一個(gè)HelloComponent,作為入?yún)?// 返回一個(gè)HocComponent作為新的組件
const HocComponent = withComponent(HelloComponent)

function App() {
  return (
    <div className="App">
      <h2>Hello HOC - Highter Order Component</h2>
      <HocComponent />
    </div>
  );
}
export default App;

可以正常工作.

![高階組件簡(jiǎn)單使用images.jianshu.io/upload_images/2701794-d79d78664a4895aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


將邏輯復(fù)用(功能擴(kuò)展)邏輯設(shè)定在高階組件中.

上述例子,僅演示了高階組件的用法和原理.

這次,我們把邏輯復(fù)用和功能擴(kuò)展加上去.

這么一個(gè)例子

  • 有兩組件. FooBar.
  • FooBar 組件的功能就是在屏幕視口寬度發(fā)生改變是,動(dòng)態(tài)的把寬度數(shù)值顯示出來(lái).

import React from 'react'
import './App.css';
/**
 * 
 * 官方定義高階組件(HOC)是 React 中用于**復(fù)用組件邏輯**的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。
   HOC 是單詞 Heigher Order Component 縮寫
   具體而言,高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。
 * 
 * 
 */

class Foo extends React.PureComponent {
  state = {
    sw: document.documentElement.clientWidth
  }

  componentDidMount () {
    window.addEventListener('resize', () => {
      this.setState(() => ({ sw: document.documentElement.clientWidth }))
    }, false)
  }

  componentWillUnmount () {
    window.removeEventListener('resize')
  }

  render () {
    return (
      <p className='FooContent'>當(dāng)前的屏幕寬度為:{this.state.sw}</p>
    )
  }
}

class Bar extends React.PureComponent {
  state = {
    sw: document.documentElement.clientWidth
  }

  componentDidMount () {
    window.addEventListener('resize', () => {
      this.setState(() => ({ sw: document.documentElement.clientWidth }))
    }, false)
  }

  componentWillUnmount () {
    window.removeEventListener('resize')
  }

  render () {
    return (
      <button className='btn-content'>當(dāng)前屏幕寬度為:{this.state.sw}</button>
    )
  }
}

function App () {
  return (
    <div className="App">
      <h2>Hello HOC - Highter Order Component</h2>
      <Foo />
      <Bar />
    </div>
  );
}
export default App;

效果如圖:

[圖片上傳失敗...(image-c468a2-1642682879317)]

功能確實(shí)實(shí)現(xiàn)了.但是兩組件除了渲染的位置,其他地方都是一致的.

Vue中,我們可以使用 mixins 來(lái)解決組件間邏輯重復(fù)定義的問題.

state , componentDidMount, componentWillUnmount 邏輯重復(fù).

React 中,我們就可以使用 Highter Order Component 高階組件的方式,來(lái)抽取組件重復(fù)定義的邏輯部分.

// 定義一個(gè)高階組件函數(shù),來(lái)抽取邏輯重復(fù)的位置,提高邏輯復(fù)用.
const withResize = (Component) => {
    //xxxxx
}

具體代碼如下:

import React from 'react'
import './App.css';
/**
 * 
 * 官方定義高階組件(HOC)是 React 中用于**復(fù)用組件邏輯**的一種高級(jí)技巧。HOC 自身不是 React API 的一部分,它是一種基于 React 的組合特性而形成的設(shè)計(jì)模式。
   HOC 是單詞 Heigher Order Component 縮寫
   具體而言,高階組件是參數(shù)為組件,返回值為新組件的函數(shù)。
 * 
 * 
 */

class Foo extends React.PureComponent {
  // state = {
  //   sw: document.documentElement.clientWidth
  // }

  // componentDidMount () {
  //   window.addEventListener('resize', () => {
  //     this.setState(() => ({ sw: document.documentElement.clientWidth }))
  //   }, false)
  // }

  // componentWillUnmount () {
  //   window.removeEventListener('resize')
  // }

  render () {
    return (
      <p className='FooContent'>當(dāng)前的屏幕寬度為:{this.props.sw}</p>
    )
  }
}

class Bar extends React.PureComponent {
  // state = {
  //   sw: document.documentElement.clientWidth
  // }

  // componentDidMount () {
  //   window.addEventListener('resize', () => {
  //     this.setState(() => ({ sw: document.documentElement.clientWidth }))
  //   }, false)
  // }

  // componentWillUnmount () {
  //   window.removeEventListener('resize')
  // }

  render () {
    return (
      <button className='btn-content'>當(dāng)前屏幕寬度為:{this.props.sw}</button>
    )
  }
}

// 定義一個(gè)高階組件函數(shù),來(lái)抽取邏輯重復(fù)的位置,提高邏輯復(fù)用.
const withResize = (Component) => {
  return class WrappedComponent extends React.PureComponent {
    //#region 抽離組件通用的邏輯部分
    state = {
      sw: document.documentElement.clientWidth
    }

    componentDidMount () {
      window.addEventListener('resize', () => {
        this.setState(() => ({ sw: document.documentElement.clientWidth }))
      }, false)
    }

    componentWillUnmount () {
      window.removeEventListener('resize')
    }
    //#endregion

    render () {
      // 將需要的數(shù)據(jù)以 props 的方式傳遞給被包裝的組件
      return <Component {...this.state} />
    }
  }
}

const FooWithResize = withResize(Foo)
const BarWithResize = withResize(Bar)

function App () {
  return (
    <div className="App">
      <h2>Hello HOC - Highter Order Component</h2>
      <h3>將通用邏輯抽離,以便復(fù)用!</h3>
      {/* <Foo />
      <Bar /> */}
      <FooWithResize />
      <BarWithResize />
    </div>
  );
}
export default App;


  • 將通用邏輯從 FooBar 組件中抽離.起到邏輯復(fù)用的作用.
  • FooBar 需要的數(shù)據(jù)以 props 的形式傳入即可.
高階組件抽取通用邏輯以便復(fù)用.gif

效果和上述是一致的.


總結(jié)

  • 高階組件就是一個(gè)函數(shù)僅此而已(javascript中不就是函數(shù)和對(duì)象嗎?)
  • 高階組件接受一個(gè)組件(可以是函數(shù)組件,也可以是class 組件)作為參數(shù)(普通函數(shù),構(gòu)造函數(shù)).
  • 返回一個(gè)新組件(可以是函數(shù)組件,也可是 class 組件),返回一個(gè)普通函數(shù)或者是構(gòu)造函數(shù).
  • 所以高階組件也是一個(gè)高階函數(shù).
  • 將通用的邏輯抽離在高階組件中,已達(dá)到復(fù)用的目的.

碼云地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容