React組件二次包裝的具體實現(xiàn)
原生組件是對公共場景的抽象,若要契合實際業(yè)務(wù)往往需要對其進行二次包裝。
對組件進行二次包裝一般需要進行包括不限于以下的步驟:
- 組件類型類型聲明
- 自定義組件渲染邏輯
- 向原生組件透傳屬性
1. 類型聲明
類型聲明是組件二次包裝過程中的第一步,項目中常見的方案是直接進行類型聲明,例如通過Button組件包裝個自定義的Button:
import React, { CSSProperties } from "react";
import { Button } from "@arco-design/web-react";
type IProps = {
? style?: CSSProperties;
? className?: string | string[];
? type?: "default" | "primary" | "secondary" | "dashed" | "text" | "outline";
? // ...其他Button屬性
};
const MyButton: React.FC<IProps> = ({ style, className, type, children }) => {
? // 此處為自定義邏輯
? return (
? ? <Button style={style} className={className} type={type}>
? ? ? {children}
? ? </Button>
? );
};
export default MyButton;直接類型聲明簡單粗暴,用到什么屬性就添加什么,但存在一個致命的,其限定了原生組件提供的能力,降低了二次包裝的自定義組件的可用性。
因此更為好的方案是類型繼承,不僅繼承類型,也繼承屬性:
import React from "react";
import { Button, ButtonProps } from "@arco-design/web-react";
// 繼承類型
type IProps = ButtonProps & {};
const MyButton: React.FC<IProps> = (props) => {
? // 此處為自定義邏輯
? // 繼承屬性
? return <Button {...props} />;
};
export default MyButton;2. 默認屬性
開源組件庫提供的組件滿足了日常項目的開發(fā)需求,但開源項目畢竟是面對公共場景,其組件默認值并不能匹配實際的業(yè)務(wù)場景,因此我們通常需要在二次包裝自定義組件的時候重置默認值。
常見的重置方案也是直接重置:
import React from "react";
import { Button, ButtonProps } from "@arco-design/web-react";
type IProps = ButtonProps & {};
const MyButton: React.FC<IProps> = (props) => {
? const { size = "large", type = "primary" } = props;
? return <Button size={size} type={type} {...props} />;
};
export default MyButton;這種方式很直觀,也沒有任何問題。但追求極致的各位大佬們,肯定在重置多個自定義組件的過程中厭煩了這種重復(fù)的寫法。
因此更好的方式是使用高階組件,首先先定義一個通用的Hoc:
import React from "react";
/**
?* 組件默認屬性Hoc
?* @param defaultProps 默認屬性
?* @returns
?*/
export function withDefaultProps<P = {}>(defaultProps?: Partial<P>) {
? return function (Component: any) {
? ? const WrappedComponent: React.FC<P> = (props) => {
? ? ? return React.createElement(Component, {
? ? ? ? ...defaultProps,
? ? ? ? ...props,
? ? ? });
? ? };
? ? WrappedComponent.displayName = `withDefaultProps(${getDisplayName(
? ? ? Component
? ? )})`;
? ? return WrappedComponent;
? };
}這時候?qū)傩灾刂镁蜁兊糜袃|點點優(yōu)雅了:
import React from "react";
import { Button, ButtonProps } from "@arco-design/web-react";
type IProps = ButtonProps & {};
export default withDefaultProps<IProps>({
? size: "large",
? type: "primary",
})(Button);通過組件默認屬性Hoc可以有效抽離包裝業(yè)務(wù)組件,優(yōu)化代碼結(jié)構(gòu)。
3. 自定義屬性與屬性透傳
二次包裝組件的當(dāng)然不僅僅只包含原生組件的屬性,還有新增的自定義屬性,例如下面定義的組件:
import React, { useEffect } from "react";
import { Button, ButtonProps } from "@arco-design/web-react";
type IProps = ButtonProps & {
? hello?: string;
};
const MyButton: React.FC<IProps> = (props) => {
? useEffect(() => console.log(props.hello), [props.hello]);
? return <Button {...props} />;
};
export default withDefaultProps<IProps>({
? hello: "world",
})(MyButton);上述代碼中未過濾自定義屬性,可能會導(dǎo)致原生組件接收非聲明的屬性導(dǎo)致渲染異常(例如Antd組件會將未聲明屬性渲染為文檔標(biāo)簽屬性,輸出控制臺錯誤)。
因此往往需要做自定義屬性過濾后再進行透傳,過濾方式包括不限于以下這些:
- 通過拓展運算符
- 通過omit函數(shù)
改造后代碼如下:
import React, { useEffect } from "react";
import { Button, ButtonProps } from "@arco-design/web-react";
type IProps = ButtonProps & {
? hello?: string;
};
/// 這里通過拓展運算符過濾原生組件未聲明屬性
const MyButton: React.FC<IProps> = ({ hello, ...restProps }) => {
? useEffect(() => console.log(hello), [hello]);
? return <Button {...restProps} />;
};
export default withDefaultProps<IProps>({
? hello: "world",
})(MyButton);
到此這篇關(guān)于React組件二次包裝的具體實現(xiàn)的文章就介紹到這了,更多相關(guān)React組件二次包裝裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react-router browserHistory刷新頁面404問題解決方法
本篇文章主要介紹了react-router browserHistory刷新頁面404問題解決方法,非常具有實用價值,需要的朋友可以參考下2017-12-12
webpack4+react多頁面架構(gòu)的實現(xiàn)
webpack在單頁面打包上應(yīng)用廣泛,以create-react-app為首的腳手架眾多。這篇文章主要介紹了webpack4+react多頁面架構(gòu)的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10
jsoneditor二次封裝實時預(yù)覽json編輯器組件react版
這篇文章主要為大家介紹了jsoneditor二次封裝實時預(yù)覽json編輯器組件react版示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
react?echarts?tree樹圖搜索展開功能示例詳解
這篇文章主要為大家介紹了react?echarts?tree樹圖搜索展開功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01

