React组件二次包装的具体实现

 更新时间:2022年02月16日 14:58:03   作者:Pwcong  
本文主要介绍了React组件二次包装的具体实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

原生组件是对公共场景的抽象,若要契合实际业务往往需要对其进行二次包装。
对组件进行二次包装一般需要进行包括不限于以下的步骤:

  • 组件类型类型声明
  • 自定义组件渲染逻辑
  • 向原生组件透传属性

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. 默认属性

开源组件库提供的组件满足了日常项目的开发需求,但开源项目毕竟是面对公共场景,其组件默认值并不能匹配实际的业务场景,因此我们通常需要在二次包装自定义组件的时候重置默认值。
常见的重置方案也是直接重置:

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;

这种方式很直观,也没有任何问题。但追求极致的各位大佬们,肯定在重置多个自定义组件的过程中厌烦了这种重复的写法。
因此更好的方式是使用高阶组件,首先先定义一个通用的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;
  };
}

这时候属性重置就会变得有亿点点优雅了:

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可以有效抽离包装业务组件,优化代码结构。

3. 自定义属性与属性透传

二次包装组件的当然不仅仅只包含原生组件的属性,还有新增的自定义属性,例如下面定义的组件:

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);

上述代码中未过滤自定义属性,可能会导致原生组件接收非声明的属性导致渲染异常(例如Antd组件会将未声明属性渲染为文档标签属性,输出控制台错误)。
因此往往需要做自定义属性过滤后再进行透传,过滤方式包括不限于以下这些:

  • 通过拓展运算符
  • 通过omit函数

改造后代码如下:

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);

到此这篇关于React组件二次包装的具体实现的文章就介绍到这了,更多相关React组件二次包装装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • TS装饰器bindThis优雅实现React类组件中this绑定

    TS装饰器bindThis优雅实现React类组件中this绑定

    这篇文章主要为大家介绍了TS装饰器bindThis优雅实现React类组件中this绑定,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • React工作流程及Error Boundaries实现过程讲解

    React工作流程及Error Boundaries实现过程讲解

    这篇文章主要介绍了React工作流程及Error Boundaries实现过程讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-02-02
  • react中使用Modal.confirm数据不更新的问题完美解决方案

    react中使用Modal.confirm数据不更新的问题完美解决方案

    这篇文章主要介绍了react中使用Modal.confirm数据不更新的问题解决方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • React特征学习之Form格式示例详解

    React特征学习之Form格式示例详解

    这篇文章主要为大家介绍了React特征学习之Form格式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 使用React Hooks模拟生命周期的实现方法

    使用React Hooks模拟生命周期的实现方法

    这篇文章主要介绍了使用React Hooks模拟生命周期,本文举例说明如何使用 hooks 来模拟比较常见的 class 组件生命周期,需要的朋友可以参考下
    2023-02-02
  • 使用react的7个避坑案例小结

    使用react的7个避坑案例小结

    React是个很受欢迎的前端框架。今天我们探索下React开发者应该注意的七点,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • 手挽手带你学React之React-router4.x的使用

    手挽手带你学React之React-router4.x的使用

    这篇文章主要介绍了手挽手带你学React之React-router4.x的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-02-02
  • 深入了解React中的合成事件

    深入了解React中的合成事件

    React 中的事件,是对原生事件的封装,叫做合成事件。这篇文章主要通过几个简单的示例为大家详细介绍一下React中的合成事件,感兴趣的可以了解一下
    2023-02-02
  • 三分钟搞懂react-hooks及实例代码

    三分钟搞懂react-hooks及实例代码

    React Hooks是今年最劲爆的新特性真的毫不夸张。如果你也对react感兴趣,或者正在使用react进行项目开发,请抽出点时间阅读下此文
    2022-03-03
  • react.js组件实现拖拽复制和可排序的示例代码

    react.js组件实现拖拽复制和可排序的示例代码

    这篇文章主要介绍了react.js组件实现拖拽复制和可排序的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08

最新评论