搜尋
首頁web前端js教程React高階元件是什麼? React高階元件的詳細講解

本篇文章帶給大家的內容是關於React高階元件是什麼? React高階元件的詳細講解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、基本概念

高階函數是以函數為參數,並且傳回也是函數的的函數。類似的,高階元件(簡稱HOC)接收 React 元件為參數,並且傳回一個新的React元件。高階組件本質也是函數,並不是組件。高階組件的函數形式如下:

const EnhanceComponent = higherOrderComponent(WrappedComponent)

透過一個簡單的例子解釋高階元件是如何重複使用的。現在有一個元件MyComponent,需要從LocalStorage取得數據,然後渲染到介面。一般情況下,我們可以這樣實作:

import React, { Component } from 'react'

class MyComponent extends Component {
  componentWillMount() {
    let data = localStorage.getItem('data');
    this.setState({data});
  }
  render() {
    return(
      <div>{this.state.data}</div>
    )
  }
}

程式碼很簡單,但當其它元件也需要從LocalStorage 取得相同的資料展示出來時,每個元件都需要重寫一次componentWillMount 中的程式碼,這顯然是很冗餘的。下面讓我人來看看使用高階元件改寫這部分程式碼。

import React, { Component } from 'react'

function withPersistentData(WrappedComponent) {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem('data');
      this.setState({data});
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <wrappedcomponent></wrappedcomponent>
    }
  }
}

class MyComponent extends Component{
  render() {
    return <p>{this.props.data}</p>
  }
}

const MyComponentWithPersistentData = withPersistentData(MyComponent);

withPersistentData 就是一個高階元件,它傳回一個新的元件,在新元件中componentWillMount 中統一處理從LocalStorage 取得資料邏輯,然後將取得到的資料透過props 傳遞給被包裝的元件WrappedComponent,這樣在WrappedComponent中就可以直接使用this.props.data 取得需要展示的數據,當有其他的元件也需要這段邏輯時,繼續使用withPersistentData 這個高階元件包裝這些元件。

二、使用場景

高階元件的使用場景主要有以下4:
1)操縱props
2) 透過ref 存取元件實例
3)元件狀態提升
4)用其他元素包裝元件

1.操縱props

在被包裝元件接收props 前,高階元件可以先攔截到props, 對props 執行增加、刪除或修改的操作,然後將處理後的props 再傳遞被包裝組件,一中的例子就是屬於這種情況。

2.透過 ref 存取元件實例

高階元件 ref 取得被包裝元件實例的引用,然後高階元件就具備了直接運算被包裝元件的屬性或方法的能力。

import React, { Component } from 'react'

function withRef(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.someMethod = this.someMethod.bind(this);
    }

    someMethod() {
      this.wrappedInstance.comeMethodInWrappedComponent();
    }

    render() {
      // 为被包装组件添加 ref 属性,从而获取组件实例并赋值给 this.wrappedInstance
      return <wrappedcomponent> { this.wrappedInstance = instance }} {...this.props}/>
    }
  }
}</wrappedcomponent>

當 wrappedComponent 被渲染時,執行 ref 的回呼函數,高階元件透過 this.wrappedInstance 儲存 wrappedComponent 實例引用,在 someMethod 中透過 this.wrappedInstance 呼叫 wrappedComponent 中的方法。這種用法在實際專案中很少會被用到,但當高階組件封裝的複用邏輯需要被包裝組件的方法或屬性的協同支持時,這種用法就有了用武之地。

3.元件狀態提升

高階元件可以透過將被包裝組件的狀態及對應的狀態處理方法提升到高階元件本身內部實現被包裝元件的無狀態化。一個典型的場景是,利用高階元件將原本受控元件需要自行維護的狀態統一提升到高階元件中。

import React, { Component } from 'react'

function withRef(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.state = {
        value: ''
      }
      this.handleValueChange = this.handleValueChange.bind(this);
    }

    handleValueChange(event) {
      this.this.setState({
        value: event.EventTarget.value
      })
    }

    render() {
      // newProps保存受控组件需要使用的属性和事件处理函数
      const newProps = {
        controlledProps: {
          value: this.state.value,
          onChange: this.handleValueChange
        }
      }
      return <wrappedcomponent></wrappedcomponent>
    }
  }
}

這個例子把受控元件value 屬性用到的狀態和處理value 變化的回呼函數都提升到高階元件中,當我們再使用受控元件時,就可以這樣使用:

import React, { Component } from 'react'

function withControlledState(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.state = {
        value: ''
      }
      this.handleValueChange = this.handleValueChange.bind(this);
    }

    handleValueChange(event) {
      this.this.setState({
        value: event.EventTarget.value
      })
    }

    render() {
      // newProps保存受控组件需要使用的属性和事件处理函数
      const newProps = {
        controlledProps: {
          value: this.state.value,
          onChange: this.handleValueChange
        }
      }
      return <wrappedcomponent></wrappedcomponent>
    }
  }
}


class  SimpleControlledComponent extends React.Component {
  render() {
    // 此时的 SimpleControlledComponent 为无状态组件,状态由高阶组件维护
    return <input>
  }
}

const ComponentWithControlledState = withControlledState(SimpleControlledComponent);

三、參數傳遞

高階元件的參數並非只能是一個元件,它還可以接收其他參數。例如一中是從 LocalStorage 取得 key 為 data的數據,當需要取得資料的 key不確定時,withPersistentData 這個高階元件就不滿足需求了。我們可以讓它接收一個額外參數來決定從LocalStorage 中取得哪個資料:

import React, { Component } from 'react'

function withPersistentData(WrappedComponent, key) {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem(key);
      this.setState({ data });
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <wrappedcomponent></wrappedcomponent>
    }
  }
}

class MyComponent extends Component {
  render() {
    return <p>{this.props.data}</p>
  }
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData(MyComponent, 'data');

// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData(MyComponent, 'name');

新版本的withPersistentData 滿足取得不同key 值的需求,但實際情況中,我們很少使用這種方式傳遞參數,而是採用更靈活、更具能用性的函數形式:

HOC(...params)(WrappedComponent)

HOC(...params) 的返回值是一個高階元件,高階元件需要的參數是先傳遞HOC 函數的。用這種形式改寫withPersistentData 如下(注意:這種形式的高階元件使用箭頭函數定義更為簡潔):

import React, { Component } from 'react'

const withPersistentData = (key) => (WrappedComponent) => {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem(key);
      this.setState({ data });
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <wrappedcomponent></wrappedcomponent>
    }
  }
}

class MyComponent extends Component {
  render() {
    return <p>{this.props.data}</p>
  }
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData('data')(MyComponent);

// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData('name')(MyComponent);

四、繼承方式實作高階元件

前面介紹的高階元件的實作方式都是由高階元件處理通用邏輯,然後將相關屬性傳遞給被包裝元件,我們稱這種方式為屬性代理。除了屬性代理外,還可以透過繼承方式實現高階元件:透過 繼承被包裝元件實現邏輯的複用。繼承方式實現的高階元件常用於渲染劫持。例如,當使用者處於登入狀態時,允許元件渲染,否則渲染一個空元件。程式碼如下:

function withAuth(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      if (this.props.loggedIn) {
        return super.render();
      } else {
        return null;
      }
    }
  }
}

根據WrappedComponent的 this.props.loggedIn 判讀使用者是否已登錄,如果登錄,就透過 super.render()呼叫WrappedComponent 的render 方法正常渲染元件,否則傳回一個null,繼承方式實現高階元件對被包裝元件具有侵入性,當組合多個高階使用時,很容易因為子類別元件忘記透過super呼叫父類別元件方法而導致邏輯遺失。因此,在使用高階元件時,應盡量透過代理方式實現高階元件。

相關推薦:

超級給力的JavaScript的React框架入門教學_基礎知識

#MySQL高可用元件MHA參數詳解

##############################################################

以上是React高階元件是什麼? React高階元件的詳細講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript是用C編寫的嗎?檢查證據JavaScript是用C編寫的嗎?檢查證據Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在行動中:現實世界中的示例和項目JavaScript在行動中:現實世界中的示例和項目Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。