如何开发一个好用的公共组件

news2025/4/6 7:23:54

写在前面

当你对某一个业务场景有自己的理解,想提炼开发了一个很好用的组件,想开放给别的同学使用,或者甚至放在社区给任何一个人使用,你应该会产生以下疑问:

  • 一个标准的组件是怎么样的,在开发过程中有哪些注意事项?
  • 组件打包过程是怎样的,如何按需加载?
  • 别人要如何没有负担的使用我的组件?
  • 组件如何支持同步和异步使用?
  • 如何更好的维护独立组件库?

基于以上疑问,我们开始这篇阅读这篇文章

组件设计

如何让别人清晰的使用你的组件,换位思考一下,你在使用别人的组件的时候,什么样的组件是你用起来十分符合预期甚至超出预期的?什么样的组件让你在用的时候,充满问号,产生“不如自己写一个”的想法?

首先要让使用者知道你的组件的主要功能README.md),其次知道怎么用能满足自己的需求(props)。

一个好的README.md应该像antdelementUI的官方文档那样,写清楚props用法,有相应的示例展示,必要的时候使用mock数据支持基本的样式展示。

举个例子(antd):

除此之外,第一次开发独立组件或者独立组件库,还应该注意什么呢?

清晰的types类型定义&导出

清晰的类型定义不仅能降低组件使用门槛,也能使组件减少大部分js错误(例如类型错误,取值为空错误等)。

export interface BaseButtonProps {type?: ButtonType;icon?: React.ReactNode; /** * Shape of Button * * @default default // ✅ 类型注释默认值 */shape?: ButtonShape;size?: SizeType;disabled?: boolean;loading?: boolean | { delay?: number };prefixCls?: string;className?: string;ghost?: boolean;danger?: boolean;block?: boolean;children?: React.ReactNode; // ✅ 开放插槽
}

export type AnchorButtonProps = {href: string;target?: string;onClick?: React.MouseEventHandler<HTMLElement>;
} & BaseButtonProps &Omit<React.AnchorHTMLAttributes<any>, 'type' | 'onClick'>;

// ✅ 开放原生props 
export type NativeButtonProps = {htmlType?: ButtonHTMLType;onClick?: React.MouseEventHandler<HTMLElement>;
} & BaseButtonProps &Omit<React.ButtonHTMLAttributes<any>, 'type' | 'onClick'>;

export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>; 

可扩展插槽(ReactNode)

提供可消费插槽,允许消费方使用自定义children做进一步扩展。

// 扩展插槽
const {iconNode,kids} = props
 let ButtonNode = (<button{...(rest as NativeButtonProps)}type={htmlType}className={classes}onClick={handleClick}disabled={mergedDisabled}ref={buttonRef}>{iconNode}{kids}</button>); 

开放与消费底层组件Props

如果你的组件是基于elementUIantd等底层组件库做了进一步封装,满足更强大的定制需求,不要忘了保留底层组件的原有功能。

  • Props写法:自定义Props extends 底层组件Props(可以通过lib单独引入Props类型)
//此处引入只是为了方便解释,实际项目并非如此,请自行查阅相关组件源码以及文档
import { SelectProps } from 'antd/next/types/select';
import { ISelection } from 'antd/lib/hooks/select/hook';
// 定义props
export interface IEmployeeSelectPropsextends Omit<SelectProps, 'mode' | 'onChange'>,Pick<ISelection, 'maxSelection' | 'mode' | 'onChange'> {customPropsA?: string[];customPropsB?: string[];/** * 自定义接口 */list?: QueryListInfoType;...
} 
  • 如何接收并消费传入的底层组件Props解构赋值
// 接收
const { customPropsA, customPropsB, ...rest } = props;

// 消费
 <Select{...rest}onChange={customPropsA}onSearch={customPropsB}.../> 

受控组件与非受控组件

受控组件就是支持被Reactstate控制的组件,简单来讲,可以通过下传valueonChange控制组件值。同理反推,非受控组件没有和Reactstate绑定,只能通过绑定 Ref单向获得组件值(ref.current.value)。

因此,通常来讲,一个好用的公共组件需要支持受控模式和非受控模式,能够满足普通用户的最简使用需求(组件内部自己维护状态),也能够满足高级用户的自定义需求(由使用方传入state值和onChange方法)。

这里推荐使用ahooks的useControllableValue,它支持父组件下传state,如果没有下传,则交由组件内部管理状态值

举个例子:

const [visible, onVisibleChange] = useControllableValue(props, {trigger: 'onVisibleChange',defaultValuePropName: 'defaultVisible',valuePropName: 'visible',}); 

样式隔离与CSS变量的使用

CSS没有作用域概念,引入即全局生效,但一个样式是否起作用由多个因素共同决定(重要程度、优先级、样式加载顺序)。组件使用者肯定不希望组件层级的样式影响到全局样式,为了避免样式冲突,我们就需要对样式进行隔离。

一般来讲,我们会在组件内部使用一个特定的前缀,例如element-ui使用el-作为前缀。

举例sass语法:

$css_prefix: $css-prefix: 'abc-module-' !default;
$content-border-color: rgba(159, 183, 249, 0.5);


.#{$css_prefix}button {background-color: $content-border-color;
} 

如果你想开发的是一组统一风格的组件库,那么推荐使用css变量,这样方便外部使用者通过改变css变量值的方式统一调整散落在页面各处的组件的样式风格。

组件多语言以及埋点

如果你的组件涉及国际化相关的,或想开放到社区,让各国的开发中都使用,那么组件的多语言处理是必不可少的,可以使用模版动态注入变量值,并且要设置好默认的兜底文案。

其次就是曝光埋点,可以让你清晰的看到组件的使用情况,可以更好的帮助你改进自己的组件,从而让更多的人使用它。

组件导出方式

组件导出方式取决于你想让使用方如何使用,如果你是单个独立组件,通过在入口文件以这样的方式导出:

import PageProduct from './components/you-module';
export { default as PageProduct } from './components/you-module';
export default PageProduct;
// 导出必要的types
export type { IProductProps } from './components/you-module'; 

// 消费方使用
import PageProductfrom '组件';

// 单独引入types类型定义
import type IProductProps from '组件'; 

如果是组件库,可以这样导出:

export { default as PageProduct1 } from './components/you-module1';
export { default as PageProduct2 } from './components/you-module2';

// 消费方使用
import { PageProduct1,PageProduct2 } from '组件库'; 

组件调试

开发阶段可以配合文档工具,例如dumivitePress等静态站点工具,可以在开发过程中调试,所见即所得。

打包构建

开发完成后,利用打包工具打包构建生成生产文件。

单元测试

如果你的组件逻辑十分复杂,依赖异步数据返回有不同的表现,那么最好添加单元测试,保证每次正式发布之前。新的迭代不会影响老的功能。单元测试推荐使用Jest

组件发布

修改package.json配置文件,登陆npm账号将组件发布至npm.

// 控制台会返回下一个小版本号 如v1.0.1 
npm version patch 
// 重新发布 
npm publish 

组件使用

组件在打包构建的时候,通过不同的配置会形成不同的产物,当然也会有不同的引入方式。“同步引入”是指消费方直接npm install package ,在项目代码库中通过ES Module的方式引入使用。“异步引入”方式通常通过请求一个独立的js文件来加载并使用组件。

通常来讲,如果是独立组件,且不是首屏强依赖组件,推荐使用异步加载方式。如果是组件库,最好使用同步加载方式,通过ESM语法进行Tree Shaking,实现按需引入。

总结

组件是对我们最常用的场景的一些提炼,是为了让我们可以快速开发出想要的功能,而无需再从头开始,因此通用性、可扩展性、使用便捷简单、完善的API等特点是衡量一个组件是否好用的最重要的指标。

好了,如此我们就完成了对一个组件从开发到发布、再到使用的全部过程,是不是很简单呢?快去开发属于你自己的公共组件吧。

最后

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/345212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

android-java同步方法和异步方法

接口 Java接口是一系列方法的声明&#xff0c;是一些方法特征的集合&#xff0c;一个接口只有方法的特征没有方法的实现&#xff0c;因此这些方法可以在不同的地方被不同的类实现&#xff0c;而这些实现可以具有不同的行为&#xff08;功能&#xff09;。 两种含义&#xff1a…

中文编程发展不起来,无代码开发能否打个翻身仗

中文编程夹缝里生存众所周知&#xff0c;易语言开创了中文编写程序的先河&#xff0c;最早可追溯到2000年。当时易语言风靡一时&#xff0c;背后积攒了大批的用户&#xff0c;承载着那一代人的青春。也帮助了很多普通的初学者能够在短时间的入门。如今的易语言早已失去了往日的…

大咖说·图书分享|狼书(卷3):Node.js高级技术

Node.js都有哪些需要掌握的高级技术&#xff1f;前端为什么同样需要学习&#xff1f; Node.js未来的发展趋势究竟如何&#xff1f;本期大咖说&#xff0c;Node布道师桑世龙携新作《狼书(卷3)&#xff1a;Node.js高级技术》展开分享。 ● 嘉宾介绍 桑世龙&#xff1a;Node布道…

博客系统 SSM 超强硬核良心推荐之第一弹 - 预备工作

硬核 ! 从 0 到 1 完美实现 SSM 版本的博客系统 , 学会保准不吃亏!一 . SSM 版本相比于 Servlet 版本的亮点二 . 初始化数据库三 . 前端页面3.1 注册页面3.2 登录功能3.3 文章总列表页3.4 自己的文章列表页3.5 文章详情页3.6 编写博客页面大家好 , 这是新的专栏 , 博客系统 SSM…

嵌入式Linux学习经典书籍-学完你就是高手

很多刚入门的朋友一直都有人问我要学习资料&#xff0c;嵌入式实在太杂&#xff0c;网上很多人写的太不负责了&#xff0c;本书单综合了本人以及一些朋友多年的经验整理而成。 本人见识和阅读量有限&#xff0c;本书单可能有不对的地方&#xff0c;欢迎朋友指正&#xff0c;交…

SCI写作,一定要避开这些“雷点”!

SCI论文写作中&#xff0c;除了要符合各部分的写作要求&#xff0c;还有许多细节问题需要我们注意&#xff0c;不然可能一不小心就会“踩雷”。 今天我们就来和大家分享SCI各个部分写作时的注意事项。 下面就进入正题&#xff01; SCI写作注意事项 01 标题的拟定 1.避免使用无…

[Vivado那些事儿]将自定义 IP (HDL)添加到 Vivado 模块设计(Block Design)

绪论使用Vivado Block Design设计解决了项目继承性问题&#xff0c;但是还有个问题&#xff0c;不知道大家有没有遇到&#xff0c;就是新设计的自定义 RTL 文件无法快速的添加到Block Design中&#xff0c;一种方式是通过自定义IP&#xff0c;但是一旦设计的文件有问题就需要重…

短信链接跳转微信小程序

短信链接跳转微信小程序1 实现方案1.1 通过URL Scheme实现1.2 通过URL Link实现1.3 通过云开发静态网站实现2 实现方案对比3 实践 URL Schema 方案3.1 获取微信access_token3.2 获取openlink3.3 H5页面&#xff08;模拟短信跳转&#xff0c;验证ok&#xff09;4 问题小节4.1 io…

机器视觉_HALCON_示例实践_1.检测圆形

文章目录一、引言二、检测圆形三、总结一、引言 前面的文&#xff08;用户指南/快速向导&#xff09;差不多已经把HALCON的基本内容讲完了&#xff0c;并且在学习过程中还跑过一个简单示例——在单一背景下定位回形针。示例跑过&#xff0c;顿时觉得自己行了&#xff0c;但如果…

当make执行遇到 Arguments too long

1. 问题 Ubuntu20.04上make编译生成so的时候报错&#xff1a; make[1]:execvp:/bin/sh:Arguments too long对应makefile中的报错位置&#xff0c;仅仅是生成so的时候报错&#xff0c;伪代码如下 ${build_tool} -shared -fpic -o "$" ${OBJ_FILE} ${LDFLAGS}然而如…

Linux基础 - NTP时间同步

‍‍&#x1f3e1;博客主页&#xff1a; Passerby_Wang的博客_CSDN博客-系统运维,云计算,Linux基础领域博主 &#x1f310;所属专栏&#xff1a;『Linux基础』 &#x1f30c;上期文章&#xff1a; Linux基础 - DNS服务进阶 &#x1f4f0;如觉得博主文章写的不错或对你有所帮助…

IP地址在网络安全行业有哪些应用?

随着我国网络安全法律的颁布实施、制度的细化落实以及标准体系的制定&#xff0c;为我国产业数字化和数字产业化铺平了道路。近几年&#xff0c;数据将对网络安全行业产生巨大影响&#xff0c;包括行业数据的采集、共享&#xff0c;智能算法的演进以及算力资源的复用&#xff0…

ContextCapture Master 倾斜摄影测量实景三维建模技术应用

查看原文>>>https://mp.weixin.qq.com/s?__bizMzAxNzcxMzc5MQ&mid2247582483&idx3&sn38b94b4415ff29531e1619afe0c4df87&chksm9be29c03ac951515c28be526c987b19aedc1a5b3ad98ada5676e8c548f0f229665f495a0f281&token10630879&langzh_CN#rdCo…

Windows 11 绕过 TPM 方法总结,通用无 TPM 镜像下载 (2023 年 1 月更新)

在虚拟机、Mac 电脑和 TPM 不符合要求的旧电脑上安装 Windows 11 的通用方法总结 请访问原文链接&#xff1a;https://sysin.org/blog/windows-11-no-tpm/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 本文要解决的问题…

Qt 不规则窗口,不规则按钮,不规划控件 不规则界面

有一些特殊情况&#xff0c;需要使用不规则窗口或按钮&#xff0c;看起来非常炫酷。 类似&#xff1a; Qt 实现 不规则样式设置&#xff0c;不是视觉欺骗&#xff0c;是真正的不规则 &#xff0c;点击外面不会触发按钮的点击信号. Part1&#xff1a;不规则窗口 效果&#xf…

【软考——系统架构师】信息系统基础

&#x1f50e;这里是【软考——系统架构师】&#xff0c;关注我考试轻松过线 &#x1f44d;如果对你有帮助&#xff0c;给博主一个免费的点赞以示鼓励 欢迎各位&#x1f50e;点赞&#x1f44d;评论收藏⭐️ 文章目录&#x1f440;一、信息化概述&#x1f440;二、信息系统工程总…

json-server环境搭建及使用

json-server环境搭建 一个在前端本地运行&#xff0c;可以存储json数据的server。 基于node环境&#xff0c;可以指定一个 json 文件作为 API 的数据源。 文章目录json-server环境搭建前提下载安装监听服务启动成功修改端口号方式一&#xff1a;方式二&#xff1a;数据操作测试…

[Datawhale][CS224W]图机器学习(二)

文章目录一、概述1.1 图的结构1.2 特征处理1.3 学习任务1.3.1 节点分类1.3.2 链接预测1.3.3 图级任务二、传统方法三、统计特征与核方法3.1 节点层面3.2 连接层面3.3 图层面3.4 节点袋参考文献Datawhale开源学习社区 x 同济子豪兄 Stanford课程中文精讲系列笔记本文同时发布在&…

揭秘涨薪50%经验:从功能测试到自动化测试,我是如何蜕变的?

本人在今年互联网大环境如此严峻的情况下&#xff0c;作为一个刚毕业不到一年的初级测试&#xff0c;赶在“金三银四”依然拿到了一些面试机会&#xff0c;并且成功拿下4家公司的offer&#xff0c;其中不乏互联网大厂&#xff0c;而且最高总包给到了接近double&#xff08;无炫…

动态规划问题

目录 一、动态规划简介 二、利用动态规划解决问题 1、斐波拉契序列 2、拆分词句 3、三角形最小路径和 4、不同的路径数目&#xff08;一&#xff09; 5、带权值的最小路径和 6、求路径ii 7、01背包 8、不同子序列 9、编辑距离 10、分割回文串 一、动态规划…