最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React用法之高階組件的用法詳解

 更新時間:2023年04月17日 11:34:19   作者:翰玥  
高階組件也就是我們常說的HOC,是React中用于復用組件邏輯的一種高級技巧。這篇文章主要通過一些示例帶大家學習一下高階組件的使用,希望對大家有所幫助

監(jiān)介

高階組件也就是我們常說的HOC,是React中用于復用組件邏輯的一種高級技巧。HOC自身不是React API的一部分,他是一種基于React的組合特性而形成的設計模式。

其實就是組件作為參數(shù),返回值也是組件的函數(shù),他是純函數(shù),不會修改傳入的組件,也不會使用繼承來復制其行為。相反,HOC通過將組件包裝在容器組件中來組成新組件。HOC是純函數(shù),沒有副作用。

使用HOC的原因

  • 抽取重復代碼,實現(xiàn)組件復用:相同功能組件復用
  • 條件渲染,控制組件的渲染邏輯(渲染劫持):權限控制
  • 捕獲/劫持被處理組件的生命周期,常見場景:組件渲染性能追蹤、日志打點。

HOC的實現(xiàn)方式

先來看一個簡單的HOC實現(xiàn)方式

function withLog(Component) {
	return function (props) {
		console.log(`[${new Date().toISOString()}] ${Component.name} props:`, props);
		return <Component {...props} />;
	};
}

這個HOC接收一個組件作為參數(shù),返回一個新的組件,新的組件在渲染之前會先輸出當前時間和傳入的組件的名稱和props到控制臺,然后再將props傳遞給原始組件進行渲染。

使用這個HOC可以像下面這樣

function MyComponent(props) {
	return <div>{props.message}</div>;
}

const MyComponentWithLog = withLog(MyComponent);

ReactDOM.render(
	<MyComponentWithLog message="Hello, world!" />,
	document.getElementById('root')
);

渲染的時候控制臺會輸出

[2023-04-16T00:00:00.000Z] MyComponent props: { message: "Hello, world!" }

可以看到,HOC 可以用來增強組件的功能,比如添加日志、添加權限校驗、添加數(shù)據(jù)預處理等。

其實HOC的實現(xiàn)方式主要分為兩種:屬性代理和反向繼承

屬性代理

使用組合的方式,將組件包裝在容器上,依賴父子組件的生命周期關系來:

  • 返回無狀態(tài)的函數(shù)組件
  • 返回class組件

操作props

// 可以通過屬性代理,攔截父組件傳遞過來的porps并進行處理。

// 返回一個無狀態(tài)的函數(shù)組件
function HOC(WrappedComponent) {
  const newProps = { type: 'HOC' };
  return props => <WrappedComponent {...props} {...newProps}/>;
}

// 返回一個有狀態(tài)的 class 組件
function HOC(WrappedComponent) {
  return class extends React.Component {
    render() {
      const newProps = { type: 'HOC' };
      return <WrappedComponent {...this.props} {...newProps}/>;
    }
  };
}

抽象state

通過屬性代理無法直接操作原組件的state,可以通過props和回調(diào)函數(shù)抽象state

function HOC(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        name: '',
      };
      this.onChange = this.onChange.bind(this);
    }
    
    onChange = (event) => {
      this.setState({
        name: event.target.value,
      })
    }
    
    render() {
      const newProps = {
        name: {
          value: this.state.name,
          onChange: this.onChange,
        },
      };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };
}

// 使用
@HOC
class Example extends Component {
  render() {
    return <input name="name" {...this.props.name} />;
  }
}

這里我們稍微做一下解釋。我們主要的目的是想通過傳給HOC的這個組件來修改HOC的state,在HOC中定義了onChange方法目的是可以修改state。如果在WrappedComponent中調(diào)用onChange方法呢?我們可以定義一個對象作為WrappedComponent的props,然后將onChange方法存儲在定義的對象上,傳給WrappedComponent。

在WrappedComponent中,我們定義了一個input,我們都知道input有value屬性作為input的值,還有一個onChange方法作為change事件,我們把傳給WrappedComponent的props結構剛好就是value和onChange。這樣當input在change的時候就可以就修改state的值了。

通過props實現(xiàn)條件渲染

通過props來控制是否渲染及傳入數(shù)據(jù)

import * as React from 'react';

function HOC (WrappedComponent) {
  return (props) => (
  <div>
    {
      props.isShow ? (
        <WrappedComponent
          {...props}
        />
      ) : <div>暫無數(shù)據(jù)</div>
    }
  </div>
  );
}

export default HOC;

其他元素wrapper傳入的組件

function withBackgroundColor(WrappedComponent) {
  return class extends React.Component {
    render() {
      return (
        <div style={{ backgroundColor: '#ccc' }}>
            <WrappedComponent {...this.props} {...newProps} />
        </div>
      );
    }
  };
}

反向繼承

使用一個函數(shù)接收一個組件作為參數(shù)傳入,并返回一個繼承了該傳入組件的類組件,且在返回組件的render()方法中返回了super.render()方法。

const HOC = (WrappedComponent) => {
	return class extends WrappedComponent {
		render() {
			return super.render()
		}
	}
}
  • 允許HOC通過this訪問到原組件,可以直接讀取和操作原組件的state/ref等
  • 可以通過render.super()獲取傳入組件的render,可以有選擇的渲染劫持
  • 劫持原組件生命周期方法
function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  
  // 繼承了傳入組件
  return class HOC extends WrappedComponent {
    async componentDidMount(){
      // 劫持 WrappedComponent 組件的生命周期
      if (didMount) {
        await didMount.apply(this);
      }
      ...
    }

    render(){
      //使用 super 調(diào)用傳入組件的 render 方法
      return super.render();
    }
  }
}

讀取/操作原組件的state

function HOC(WrappedComponent){
  const didMount = WrappedComponent.prototype.componentDidMount;
  // 繼承了傳入組件
  return class HOC extends WrappedComponent {
    async componentDidMount(){
      if (didMount) {
        await didMount.apply(this);
      }
      // 將 state 中的 number 值修改成 2
      this.setState({ number: 2 });
    }

    render(){
      //使用 super 調(diào)用傳入組件的 render 方法
      return super.render();
    }
  }
}

通過this.setState({ number: 2 });修改了原組件WrappedComponent中的state的number值

條件渲染

const HOC = (WrappedComponent) =>
  class extends WrappedComponent {
    render() {
      if (this.props.isRender) {
        return super.render();
      } else {
        return <div>暫無數(shù)據(jù)</div>;
      }
    }
  }

修改react樹

// 修改返回render結果
function HigherOrderComponent(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      const tree = super.render();
      const newProps = {};
      if (tree && tree.type === 'input') {
        newProps.value = 'something here';
      }
      const props = {
        ...tree.props,
        ...newProps,
      };
      const newTree = React.cloneElement(tree, props, tree.props.children);
      return newTree;
    }
  };
}

這里首先通過super.render()拿到需要渲染的樹,然后對這個渲染樹做了修改。比如如果是一個input,則修改它的value值。

屬性代理和反向繼承對比

  • 屬性代理:從"組合"角度出發(fā),有利于從外部操作WrappedComponent,可以操作props,或者在WrappedComponent外加一些攔截器(如:條件渲染,增加外部樣式)
  • 反向繼承:從"繼承"角度出發(fā),從內(nèi)部操作WrappedComponent,可以操作組件內(nèi)部的state,生命周期和render等,功能更強大

到此這篇關于React用法之高階組件的用法詳解的文章就介紹到這了,更多相關React高階組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Input標簽自動校驗功能去除實現(xiàn)

    Input標簽自動校驗功能去除實現(xiàn)

    這篇文章主要為大家介紹了Input標簽的自動拼寫檢查功能去除實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • react 不用插件實現(xiàn)數(shù)字滾動的效果示例

    react 不用插件實現(xiàn)數(shù)字滾動的效果示例

    這篇文章主要介紹了react 不用插件實現(xiàn)數(shù)字滾動的效果示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • react 可拖拽進度條的實現(xiàn)

    react 可拖拽進度條的實現(xiàn)

    本文主要介紹了react 可拖拽進度條的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-04-04
  • react中使用usestate踩坑及解決

    react中使用usestate踩坑及解決

    這篇文章主要介紹了react中使用usestate踩坑及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • React創(chuàng)建組件的三種方式及其區(qū)別是什么

    React創(chuàng)建組件的三種方式及其區(qū)別是什么

    在React中,創(chuàng)建組件的三種主要方式是函數(shù)式組件、類組件和使用React Hooks的函數(shù)式組件,本文就詳細的介紹一下如何使用,感興趣的可以了解一下
    2023-08-08
  • React router cache route實現(xiàn)緩存頁面流程介紹

    React router cache route實現(xiàn)緩存頁面流程介紹

    react-router自身沒有路由緩存的特性,在5.x版本之前,我們可以基于react-router-cache-route來實現(xiàn)路由緩存功能。但是react-router 6.x在實現(xiàn)上做了比較大的變化,react-router-cache-route沒有提供相應的支持
    2023-01-01
  • React Fragment 和空標簽(<></>)用法及區(qū)別詳解

    React Fragment 和空標簽(<></>)用法及區(qū)別詳解

    本文詳細介紹了React中的Fragment和空標簽的使用,包括它們的區(qū)別、使用場景、性能考慮以及最佳實踐,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 一個基于react的圖片裁剪組件示例

    一個基于react的圖片裁剪組件示例

    本篇文章主要介紹了一個基于react的圖片裁剪組件示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • 解決React初始化加載組件會渲染兩次的問題

    解決React初始化加載組件會渲染兩次的問題

    這篇文章主要介紹了解決React初始化加載組件會渲染兩次的問題,文中有出現(xiàn)這種現(xiàn)象的原因及解決方法,感興趣的同學跟著小編一起來看看吧
    2023-08-08
  • 基于React的狀態(tài)管理實現(xiàn)一個簡單的顏色轉換器

    基于React的狀態(tài)管理實現(xiàn)一個簡單的顏色轉換器

    這篇文章主要介紹了用React的狀態(tài)管理,簡簡單單實現(xiàn)一個顏色轉換器,文中有詳細的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下
    2023-08-08

最新評論

中山市| 阿克| 丰台区| 文登市| 名山县| 隆子县| 怀仁县| 崇礼县| 明水县| 嫩江县| 莱州市| 新化县| 广德县| 五常市| 友谊县| 军事| 陆川县| 泗洪县| 介休市| 两当县| 贵南县| 攀枝花市| 方山县| 潼关县| 安溪县| 彰武县| 科尔| 昭觉县| 开封县| 威信县| 库车县| 桂林市| 手游| 旬阳县| 明溪县| 平陆县| 溆浦县| 印江| 松江区| 厦门市| 谷城县|