閱讀時(shí)間約為:6 分鐘。
本文首發(fā)于個(gè)人博客:React高階組件詳解:使用 TypeScript 實(shí)現(xiàn)日志記錄組件涩盾。
我們知道 React 是一個(gè)用于構(gòu)建用戶界面的 JavaScript 庫(kù)十气,其中,React 組件是 React 應(yīng)用程序的核心春霍,它們用于組合并呈現(xiàn)應(yīng)用程序的不同部分砸西。有時(shí),我們需要增強(qiáng)組件的功能址儒,但又不希望修改原始組件的代碼芹枷。這時(shí),React 高階組件(Higher-Order Components莲趣,HOC)就派上用場(chǎng)了鸳慈。
React 高階組件是一個(gè)非常強(qiáng)大的工具,可以幫助我們?cè)诓恍薷默F(xiàn)有組件的情況下增強(qiáng)組件功能妖爷。在本文中蝶涩,我們將使用 TypeScript 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志記錄高階組件示例理朋,并解釋如何編寫和使用高階組件。以演示如何使用高階組件來增強(qiáng)組件功能绿聘,而不需要修改原始組件的代碼嗽上。
什么是高階組件
高階組件是一個(gè)函數(shù),它接收一個(gè)組件作為參數(shù)熄攘,并返回一個(gè)新的組件兽愤。新組件包裝了原始組件,并增強(qiáng)了它的功能挪圾。高階組件可以用于添加共同的邏輯或功能到多個(gè)組件中浅萧,這種方法在很多情況下比繼承或組件復(fù)用更靈活。
在 React 中哲思,高階組件通常被用于以下場(chǎng)景:
- 代碼復(fù)用:將共同的邏輯提取到高階組件中洼畅,以便在多個(gè)組件中重復(fù)使用。
- 功能增強(qiáng):高階組件可以通過添加或修改 props棚赔、渲染邏輯或生命周期方法來增強(qiáng)組件的功能帝簇。
- 渲染劫持:高階組件可以通過更改組件的渲染行為來修改組件的外觀或行為。
實(shí)現(xiàn)一個(gè)日志記錄高階組件
在本文中靠益,我們將使用 TypeScript 和 React 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的日志記錄高階組件丧肴,以演示高階組件的使用方法。
首先胧后,我們定義一個(gè)高階組件函數(shù) withLogging
芋浮,它接收一個(gè)泛型參數(shù) P
,表示原始組件的 props 類型壳快。該函數(shù)返回一個(gè)新的函數(shù)組件 WithLogging
纸巷,這個(gè)組件可以包裝原始組件并添加日志信息。
import React, { FC } from 'react';
// 高階函數(shù)接收一個(gè)泛型參數(shù) P眶痰,表示原始組件的 props 類型
interface WithLoggingProps {
name: string;
}
const withLogging = <P extends object>(WrappedComponent: React.ComponentType<P>) => {
// 返回一個(gè)新的函數(shù)組件何暇,這個(gè)組件可以包裝原始組件
const WithLogging: FC<P & WithLoggingProps> = (props) => {
// 在渲染時(shí)添加日志信息
console.log(`Rendering component: ${WrappedComponent.displayName || WrappedComponent.name}`);
return <WrappedComponent {...props as P} />;
};
// 設(shè)置新組件的 displayName,便于調(diào)試
WithLogging.displayName = `WithLogging(${WrappedComponent.displayName || WrappedComponent.name})`;
return WithLogging;
};
在 withLogging
函數(shù)內(nèi)部凛驮,我們創(chuàng)建一個(gè)名為 WithLogging
的新函數(shù)組件。這個(gè)組件會(huì)接收原始組件的 props 和一個(gè)名為 name
的字符串參數(shù)条辟。在渲染時(shí)黔夭,它會(huì)打印一個(gè)帶有組件名稱的日志消息,并渲染原始組件羽嫡。我們還設(shè)置了新組件的 displayName本姥,以便更好地調(diào)試。
現(xiàn)在杭棵,我們可以使用 withLogging
高階組件來包裝一個(gè)原始組件婚惫,并增強(qiáng)它的功能氛赐。例如,我們可以創(chuàng)建一個(gè)簡(jiǎn)單的無狀態(tài)組件 Button
先舷,它只是渲染了一個(gè)按鈕艰管。
// 一個(gè)簡(jiǎn)單的無狀態(tài)組件
const Button: FC = () => {
return <button>Click me</button>;
};
現(xiàn)在,我們可以像使用 Button
一樣使用 LoggedButton
組件蒋川,但是它會(huì)在每次渲染后被點(diǎn)擊時(shí)打印一個(gè)日志消息牲芋。
// 使用高階組件包裝 Button 組件
const ButtonWithLogging = withLogging(Button);
// 渲染應(yīng)用程序組件
export default function App() {
return (
<div>
{/* 使用包裝后的 Button 組件 */}
<ButtonWithLogging name="Submit" />
</div>
);
}
使用 withLogging
高階組件,我們可以輕松地添加日志記錄和其他功能到多個(gè)組件中捺球,而不需要修改這些組件的代碼缸浦。這使得代碼更容易維護(hù),更具可讀性氮兵。
在瀏覽器中執(zhí)行上面的例子裂逐,會(huì)渲染一個(gè)包含一個(gè)按鈕的頁(yè)面,并在每次點(diǎn)擊按鈕時(shí)泣栈,在瀏覽器的控制臺(tái)中打印一條日志信息卜高。這是由于 withLogging
高階組件包裝了 Button
組件,并添加了一個(gè)事件監(jiān)聽器秩霍,在每次點(diǎn)擊按鈕時(shí)記錄一條日志篙悯。
假設(shè)這個(gè)按鈕被點(diǎn)擊了 5 次,輸出到瀏覽器控制臺(tái)的結(jié)果應(yīng)該是類似下面這樣的內(nèi)容:
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
Rendering component: WithLogging(Button)
總結(jié)
React 高階組件是一個(gè)非常強(qiáng)大的工具铃绒,可以幫助我們?cè)诓恍薷默F(xiàn)有組件的情況下增強(qiáng)組件功能鸽照。在本文中,我們使用 TypeScript 和 React 實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的日志記錄高階組件颠悬,并解釋了如何編寫和使用高階組件矮燎。通過使用高階組件,我們可以輕松地添加共同的邏輯或功能到多個(gè)組件中赔癌,使得代碼更容易維護(hù)和重用诞外。
喜歡的話,就來微信公眾號(hào)“若非的日志”一起學(xué)習(xí)啊~
微信公眾號(hào):若非的日志原創(chuàng)