iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >你知道怎么基于 React 封装一个组件吗
  • 418
分享到

你知道怎么基于 React 封装一个组件吗

2024-04-02 19:04:59 418人浏览 八月长安
摘要

目录antd 是如何封装组件的仓库地址divider 组件源代码如何暴露组件属性如何设置统一类名前缀如何处理样式与类名divider 组件样式源代码总结前言 很多小伙伴在第一次尝试封

前言

很多小伙伴在第一次尝试封装组件时会和我一样碰到许多问题,比如人家的组件会有 color 属性,我们在使用组件时传入组件文档中说明的属性值如 primary ,那么这个组件的字体颜色会变为 primary 对应的颜色,这是如何做到的?还有别人封装的组件类名都有自己独特的前缀,这是如何处理的呢,难道是 CSS 类名全部加上前缀吗,这也太麻烦了!

如果你正在困惑这些问题,你可以看看这篇文章。

我会参照 antd的divider组件 来讲述如何基于React封装一个组件,以及解答上述的一些问题,请耐心看完!

antd 是如何封装组件的

仓库地址

  • divider 组件在下图对应目录下 (代码我会拷贝过来,感兴趣的还是可以去克隆一下仓库)

divider 组件源代码

antd 的源码使用了 typescript 语法,因此不了解语法的同学要及时了解哦!

import * as React from 'react';
import classNames from 'classnames';
import { ConfiGConsumer, ConfigConsumerProps } from '../config-provider';
export interface DividerProps {
    prefixCls?: string;
    type?: 'horizontal' | 'vertical';
    orientation?: 'left' | 'right' | 'center';
    className?: string;
    children?: React.Reactnode;
    dashed?: boolean;
    style?: React.CSSProperties;
    plain?: boolean;
}
const Divider: React.FC<DividerProps> = props => (
    <ConfigConsumer>
        {({ getPrefixCls, direction }: ConfigConsumerProps) => {
            const {
                prefixCls: customizePrefixCls,
                type = 'horizontal',
                orientation = 'center',
                className,
                children,
                dashed,
                plain,
                ...restProps
            } = props;
            const prefixCls = getPrefixCls('divider', customizePrefixCls);
            const orientationPrefix = orientation.length > 0 ? `-${orientation}` : orientation;
            const hasChildren = !!children;
            const classString = classNames(
                prefixCls,
                `${prefixCls}-${type}`,
                {
                    [`${prefixCls}-with-text`]: hasChildren,
                    [`${prefixCls}-with-text${orientationPrefix}`]: hasChildren,
                    [`${prefixCls}-dashed`]: !!dashed,
                    [`${prefixCls}-plain`]: !!plain,
                    [`${prefixCls}-rtl`]: direction === 'rtl',
                },
                className,
            );
            return (
                <div className={classString} {...restProps} role="separator">
                    {children && <span className={`${prefixCls}-inner-text`}>{children}</span>}
                </div>
            );
        }}
    </ConfigConsumer>
);
export default Divider;

如何暴露组件属性

在源码中,最先看到的是以下内容,这些属性也就是divider组件所暴露的属性,我们可以 <Divider type='vertical' /> 这样来传入 type 属性,那么 divider 分割线样式就会渲染为垂直分割线,是不是很熟悉!

export interface DividerProps { // interface 是 TypeScript 的语法
    prefixCls?: string;
    type?: 'horizontal' | 'vertical'; // 限定 type 只能传入两个值中的一个
    orientation?: 'left' | 'right' | 'center';
    className?: string;
    children?: React.ReactNode;
    dashed?: boolean;
    style?: React.CSSProperties;
    plain?: boolean;
}

在上面的属性中,我们还发现 className 和 style是比较常见的属性,这代表我们可以 <Divider type='vertical' className='myClassName' style={{width: '1em'}} /> 这样使用这些属性。

如何设置统一类名前缀

我们知道,antd 的组件类名会有他们独特的前缀 ant-,这是如何处理的呢?继续看源码。

<ConfigConsumer>
    {({ getPrefixCls, direction }: ConfigConsumerProps) => {
        const {
            prefixCls: customizePrefixCls,
            type = 'horizontal',
            orientation = 'center',
            className,
            children,
            dashed,
            plain,
            ...restProps
        } = props;
        const prefixCls = getPrefixCls('divider', customizePrefixCls);

从源码中,我们发现 prefixCls ,这里是通过 getPrefixCls 方法生成,再看看 getPrefixCls 方法的源码,如下。

export interface ConfigConsumerProps {
  ...
  getPrefixCls: (suffixCls?: string, customizePrefixCls?: string) => string;
  ...
}
const defaultGetPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => {
  if (customizePrefixCls) return customizePrefixCls;
  return suffixCls ? `ant-${suffixCls}` : 'ant';
};

不难发现此时会生成的类名前缀为 ant-divider 。

如何处理样式与类名

我们封装的组件肯定是有预设的样式,又因为样式要通过类名来定义,而我们传入的属性值则会决定组件上要添加哪个类名,这又是如何实现的呢?下面看源码。

import classNames from 'classnames';
const classString = classNames(
    prefixCls,
    `${prefixCls}-${type}`,
    {
        [`${prefixCls}-with-text`]: hasChildren,
        [`${prefixCls}-with-text${orientationPrefix}`]: hasChildren,
        [`${prefixCls}-dashed`]: !!dashed,
        [`${prefixCls}-plain`]: !!plain,
        [`${prefixCls}-rtl`]: direction === 'rtl',
    },
    className,
);
return (
    <div className={classString} {...restProps} role="separator">
        {children && <span className={`${prefixCls}-inner-text`}>{children}</span>}
    </div>
);

我们发现,它通过 classNames 方法)定义了一个所有类名的常量,然后传给了 div 中的 className 属性。

其实生成的类名也就是 ant-divider-horizontal 这个样子,那么css中以此类名定义的样式也就自然会生效了。而 className 和 style 属性则是通过 {...restProps} 来传入。

最后我们再看看它的css样式代码是怎么写的!

divider 组件样式源代码

antd 组件的样式使用 Less 书写,不了解 Less 语法的同学一定要了解一下。

@import '../../style/themes/index';
@import '../../style/mixins/index';
@divider-prefix-cls: ~'@{ant-prefix}-divider'; // 可以看到这里对应的也就是之前说到的类名前缀
.@{divider-prefix-cls} {
  .reset-component();
  border-top: @border-width-base solid @divider-color;
  &-vertical { // 这里的完整类名其实就是 ant-divider-vertical, 也就是 divider 组件的 type 属性值为 vertical 时对应的样式
    position: relative;
    top: -0.06em;
    display: inline-block;
    height: 0.9em;
    margin: 0 8px;
    vertical-align: middle;
    border-top: 0;
    border-left: @border-width-base solid @divider-color;
  }
  &-horizontal {
    display: flex;
    clear: both;
    width: 100%;
    min-width: 100%; 
    margin: 24px 0;
  }
  &-horizontal&-with-text {
    display: flex;
    margin: 16px 0;
    color: @heading-color;
    font-weight: 500;
    font-size: @font-size-lg;
    white-space: nowrap;
    text-align: center;
    border-top: 0;
    border-top-color: @divider-color;
    &::before,
    &::after {
      position: relative;
      top: 50%;
      width: 50%;
      border-top: @border-width-base solid transparent;
      // Chrome not accept `inherit` in `border-top`
      border-top-color: inherit;
      border-bottom: 0;
      transfORM: translateY(50%);
      content: '';
    }
  }
  &-horizontal&-with-text-left {
    &::before {
      top: 50%;
      width: @divider-orientation-margin;
    }
    &::after {
      top: 50%;
      width: 100% - @divider-orientation-margin;
    }
  }
  &-horizontal&-with-text-right {
    &::before {
      top: 50%;
      width: 100% - @divider-orientation-margin;
    }
    &::after {
      top: 50%;
      width: @divider-orientation-margin;
    }
  }
  &-inner-text {
    display: inline-block;
    padding: 0 @divider-text-padding;
  }
  &-dashed {
    background: none;
    border-color: @divider-color;
    border-style: dashed;
    border-width: @border-width-base 0 0;
  }
  &-horizontal&-with-text&-dashed {
    border-top: 0;
    &::before,
    &::after {
      border-style: dashed none none;
    }
  }
  &-vertical&-dashed {
    border-width: 0 0 0 @border-width-base;
  }
  &-plain&-with-text {
    color: @text-color;
    font-weight: normal;
    font-size: @font-size-base;
  }
}
@import './rtl';

这样一来,我相信同学们也大概了解如何去封装一个组件以及关键点了,在源码中还有很多地方值得我们学习,比如这里的 ConfigConsumer 的定义与使用,感兴趣的同学欢迎一起交流。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!    

--结束END--

本文标题: 你知道怎么基于 React 封装一个组件吗

本文链接: https://www.lsjlt.com/news/163764.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 你知道怎么基于 React 封装一个组件吗
    目录antd 是如何封装组件的仓库地址divider 组件源代码如何暴露组件属性如何设置统一类名前缀如何处理样式与类名divider 组件样式源代码总结前言 很多小伙伴在第一次尝试封...
    99+
    2024-04-02
  • 基于React封装一个组件的方法是什么
    这篇文章主要讲解了“基于React封装一个组件的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于React封装一个组件的方法是什么”吧!antd 是如何封装组件的仓库地址divi...
    99+
    2023-06-29
  • 基于React封装组件的实现步骤
    目录前言antd 是如何封装组件的divider 组件源代码如何暴露组件属性如何设置统一类名前缀如何处理样式与类名divider 组件样式源代码前言 很多小伙伴在第一次尝试封装组件时...
    99+
    2024-04-02
  • vue 的全选组件封装你知道多少
    效果  封装的组件 <template> <el-form-item :label="label"> <el-checkbox ...
    99+
    2024-04-02
  • 你应该知道的 10 个 React Native 组件库
    编者注:本文最后更新于 2022 年 12 月 15 日,以包含更新、更受欢迎的库。 在构建 React Native 应用程序时,最佳实践涉及利用独立的 UI 组件来加快开发时间。这个想法并不是 React Nat...
    99+
    2023-09-15
    react native javascript react.js Powered by 金山文档
  • React函数式组件与类组件的不同你知道吗
    目录区别其他区别总结区别 区别函数组件类组件生命周期无有this无有state无有改变stateReact Hooks:useStatethis.setState()性能高(不用实例...
    99+
    2024-04-02
  • 基于Vue如何封装一个虚拟列表组件
    今天小编给大家分享一下基于Vue如何封装一个虚拟列表组件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。组件效果使用方法<...
    99+
    2023-07-05
  • 基于Vue实现封装一个虚拟列表组件
    目录组件效果属性插槽封装过程滚动条正常显示加载渲染大量数据不卡顿能对列表数据进行操作增删等完整代码待完善正常情况下,我们对于数据都会分页加载,最近项目中确实遇到了不能分页的场景,如果...
    99+
    2023-03-07
    Vue封装虚拟列表组件 Vue 虚拟列表组件 Vue 虚拟列表
  • React怎么封装SvgIcon组件
    本篇内容介绍了“React怎么封装SvgIcon组件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!React优雅的封装SvgIcon组件相信...
    99+
    2023-07-05
  • 基于React封装组件的实现步骤是怎样的
    这篇文章将为大家详细讲解有关基于React封装组件的实现步骤是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。前言很多小伙伴在第一次尝试封装组件时会和我一样碰到许多问题,比如人家的组件会...
    99+
    2023-06-21
  • 封装一个最简单ErrorBoundary组件处理react异常
    前言 从 React 16 开始,引入了 Error Boundaries 概念,它可以捕获它的子组件中产生的错误,记录错误日志,并展示降级内容,具体 官网地址 错误边界避免一个组...
    99+
    2024-04-02
  • 你知道怎么在HTML页面中使用React吗
    目录index.html代码:index.js代码:ReactComponentContainer.js代码:HelloReact.jsx代码:遇到的问题:Gitee代码地址:总结该...
    99+
    2024-04-02
  • 如何一步步基于element-ui封装查询组件
    目录功能基本的查询功能查询条件初始化渲染页面更多查询以及展示优化下拉组件联动查询组件扩展搜索条件展示添加功能按钮区写在最后功能 接着前一篇文章基于element-ui框架封装一个更...
    99+
    2024-04-02
  • 利用Vue3封装一个弹框组件简单吗
    目录总结放前面: 前言:公共全局弹框结语:总结放前面: Tipes: 封装弹框组件使用了Teleport,避免了组件嵌套可能导致的定位层级的隐患,还使用了defineProps,de...
    99+
    2024-04-02
  • Angular中怎么封装一个并发布组件
    本篇文章为大家展示了Angular中怎么封装一个并发布组件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、封装组件目录结构:(部分目录不是框架中自动生成,二是后期...
    99+
    2024-04-02
  • vue中怎么封装一个弹出框组件
    这期内容当中小编将会给大家带来有关vue中怎么封装一个弹出框组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.你需要先建一个弹出框的模板://首先创建一个mack.v...
    99+
    2024-04-02
  • 怎么封装一个更易用的Dialog组件
    这篇“怎么封装一个更易用的Dialog组件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么封装一个更易用的Dialog组件...
    99+
    2023-06-30
  • 基于CSS实现MaterialUI按钮点击动画并封装成 React 组件
    前言 作为一个前端框架的重度使用者,在技术选型上也会非常注意其生态和完整性.笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, ...
    99+
    2024-04-02
  • JavaScript基于inquirer封装一个控制台文件选择器
    目录前言插件效果插件实现Inquirer.jsinquirer原有参数二次封装新增参数代码实现获取指定路径下的文件列表获取指定路径下的目录列表交互类型响应控制选择文件选择目录基本类型...
    99+
    2022-11-13
    JavaScript inquirer封装控制台文件选择器 JavaScript inquirer封装
  • 怎么封装一个vue自定义日历组件
    这篇文章主要介绍“怎么封装一个vue自定义日历组件”,在日常操作中,相信很多人在怎么封装一个vue自定义日历组件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么封装一个vue自定义日历组件”的疑惑有所帮助!...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作