「前端组件化」以Antd为例,快速打通UI组件开发的任督二脉

简介: UI组件开发是前端工作的重要一环,唠一唠到底Antd的技术大神们,是怎么实现我们在官网看到的这些组件的。

前言

犹记得,我还是一个初入职场的新人,出去面试总会被问到会不会组件开发的问题。当时项目开发都使用现成的UI组件,最初用Element UI,后来换成了Antd。无论换哪种组件,都帮助节省了很多开发时间,自己平时组件开发,最多就进行一些简单的标题、弹窗、表格的二次封装。总之就是,组件开发的“道行”尚浅,所以面试的时候底气略微不足。

经过岁月的沉淀,经验的累积,自己再开发一套UI组件也不是什么麻烦事的时候,我觉得是时候可跟大家伙唠唠,到底Antd的技术大神们,是怎么实现我们在官网看到的这些组件的。

讲一个我之前年少无知的往事。最开始使用Element,还挺困惑的。就琢磨着饿了么不是送外卖的嘛,怎么还提供上技术的组件库了?后来才知道,人家的技术团队也非常非常的厉害。


「写过通用组件吗?」

这道面试题的关键在于,是怎么写的。

系统特性

现今,UI组件库丰富且成熟,所以可能觉得日常开发中,通用组件会写的很少,其实不然。

每个系统,无论是业务特性、交互特性还是UI特性,都可以整理出一部分通用组件,比如标题、页面布局、列表、可编辑表格、模糊搜索框等

以列表为例

Antd有现成的Table组件,但是我们实际开发中,一般列表管理页是带搜索项以及数据展示的,有可能还带搜索重置按钮或者搜索导出按钮。

所以通用组件就有用武之地了,一次封装,千千万万的列表管理页面就都可以用一个组件搞定了。

{!resetAble&& (
<Buttontype='primary'onClick={handleReset}>重置</Button>)}
{exportable&& (
<Buttontype='primary'onClick={handleExport}>导出</Button>)}
<TabledataSource={list} columns={columns}/>;

功能通用

已知日常开发中的部分功能确实可以做成通用组件,那么怎么界定通用的边界呢?

通用性过高会导致代码过于复杂,通用性过低,开发效率会变低。我一般会观察以下两点:

1.用到这个功能的时候,和业务可能关系不大,UI或者交互操作,在任何业务线下都需要这样设计,比如可编辑表格。

2.使用频率,这个要加一点对未来业务发展的预判。比如搜索项中的省份和城市,需要实现模糊搜索匹配的功能。

未来无论怎么样的业务,只要有省份、城市这两项基本都需要这个功能。

<Selectdisabled={disabled} allowClearvalue={value} showArrow={!showSearch} filterOption={false} showSearch={showSearch} placeholder={placeholder} onSearch={showSearch?onSearch : null} onSelect={onSelect} onClear={onClear} style={{ width }}><Select.Optionkey={item[optionValue]} value={item[optionValue]}>    {item[optionKey]}
</Select.Option></Select>;

参数设计

通用组件,差异的部分,一般在功能设计的时候会通过外部传参区分或者控制。所以开发通用组件,参数设计是重要的一个环节。

如果刚开始不是很擅长设计参数,可以参考Antd的参数设计,Antd的组件丰富且功能强大,所以参数考虑的也很周全。边学边练,效果更佳。

如图为Antd的Input输入框组件「平平无奇」的参数:

Antd组件功能赏析

电影有精彩片段赏析,Antd的组件很丰富,如果一一列举,详细介绍,可能我要写到下个月,所以我选了几个常见且基础的组件,来看看Antd是怎么设计这些组件的。

官网指路☞Ant Design

赏析前准备

学习第三方组件之前,不能盲目看代码,可能会找不到重点或者被大量的逻辑绕晕。我一般学习之前先做三方面准备:

  • 先明确组件要实现什么功能,比如输入框是否不可操作,是否回显数据等;
  • 然后看组件参数,把参数分为控制UI布局、控制内容展示、控制操作功能等几种;比如通过disabled的值控制输入框是否可以操作,通过设置value的值进行数据回显等;
  • 最后去思考这些参数怎么实现具体的功能,就比较容易想清楚了。

Grid 栅格

栅格化布局,基于行(row)和列(col)来定义信息区块,可以将区域24等分。通过 row 在水平方向建立一组 column,内容放置于 col 内。

展示层

看col文件中这三行代码,和各种style、className变量。不难发现,栅格化布局主要是通过组件参数对样式的控制来实现的。

return (
<div {...others} style={{ ...mergedStyle, ...style }} className={classes} ref={ref}>    {children}
</div>);

布局设计

结合参数说明和代码分析,可以大致总结出栅格布局的设计如下:

1.栅格组件基于 Flex 布局。

2.栅格的占位格数,也是它的宽度,样式实现时使用百分比,比如span的值为6时,24等分之后,它的百分比是25%。

.ant-col-6 {
display: block;
flex: 0025%;
max-width: 25%;
}

3.区块间隔格数的值实际上是设置的padding值的2倍,是相邻两个模块的间距之和。所以代码中进行了除以2的处理。

if (gutter&&gutter[0] >0) {
consthorizontalGutter=gutter[0] /2;
mergedStyle.paddingLeft=horizontalGutter;
mergedStyle.paddingRight=horizontalGutter;
  }

4.响应式布局,支持六个响应尺寸:xs、sm、md、lg、xl、xxl。参数支持多类型可以是number类型,也可以是Object类型。使用typeof判断参数类型。

if (typeofpropSize==='number') {
sizeProps.span=propSize;
} elseif (typeofpropSize==='object') {
sizeProps=propSize|| {};
}

布局功能分析告一段落,栅格组件赏析也就收工了。

Steps 步骤条

我们来看看步骤条的功能。

  • 步骤条状态,已完成、进行中、未开始、运行错误。
  • 两种展示方式,横向和纵向。
  • 不同展示类型,数值类、自定图标类、点状类。
  • 内容展示,标题、子标题、详情描述。

rc-steps

我在看Antd的源码时发现,有些组件底层用的第三方react-component中的组件。当然这个组件库也是属于Antd的。所以想研究Steps组件的功能,需要翻另一个组件库的代码react-componentr/steps

import RcSteps from 'rc-steps';

步骤条状态

既可以通过status直接指定当前步骤状态,也可以通过对比current和步骤的数值确定步骤的状态。

conststepNumber=initial+index;
if (status==='error'&&index===current-1) {
childProps.className=`${prefixCls}-next-error`;
}
if (!child.props.status) {
if (stepNumber===current) {
childProps.status=status;
  } elseif (stepNumber<current) {
childProps.status='finish';
  } else {
childProps.status='wait';
  }
}

展示类型

步骤条支持多种不同的展示类型,代码实现上主要是通过条件语句判断。

  • 点状类型,支持自定义展示。当点状步骤条参数progressDot的值是函数类型时,会使用传入的值;否则使用内部定义的点状展示内容。
  • 自定义图标,参数icon表示步骤图标的类型,当它有值的时候,步骤条会显示成它的值。有两个特殊的图标:成功状态、失败状态,这两个状态的图标如果使用组件时没有进行自定义,会取内部定义的图标。
  • 默认类型,放到条件判断最底层,当其他判断条件的参数没有值时,步骤条会展示内部定义的默认类型。

条件判断

内部定义的成功和失败的图标

consticons= {
finish: <CheckOutlinedclassName={`${prefixCls}-finish-icon`} />,error: <CloseOutlined className={`${prefixCls}-error-icon`} />,};

Table 表格

Antd的Table表格,功能很强大,单看文档中的使用介绍就能感觉出来,可用功能大概30多种。我带着这些功能是怎样实现的好奇心,研究了Antd的源码。内容有点多,我挑基础的部分讲一讲。

rc-table

Table组件,底层主要使用react-component中的table组件。

columns

  • 参数columns表示表格列的配置描述,表格有哪些列表项都是通过它定义的。
  • Tabel组件会将columns传入RcTable组件。
  • columns的值确定表头thead都有哪些分组。
  • tbody中表格项的值,也是通过columns中列表项的dataIndex变量,从参数dataSource中找到对应的值。
{flattenColumns.map((column: ColumnType<RecordType>, colIndex) => {
const { render, dataIndex, className: columnClassName } =column;
return (
<CellclassName={columnClassName}
ellipsis={column.ellipsis}
align={column.align}
component={cellComponent}
prefixCls={prefixCls}
key={key}
record={record}
index={index}
renderIndex={renderIndex}
dataIndex={dataIndex}
render={render}
shouldCellUpdate={column.shouldCellUpdate}
expanded={appendCellNode&&expanded}
      {...fixedInfo}
appendNode={appendCellNode}
additionalProps={additionalCellProps}
/>  );
})}

dataSource

  • Table的参数dataSource实现表格数据回显。
  • dataSource传入Tabel组件会根据分页功能处理成pageData对象,传入RcTable组件。
  • 在RcTable组件中,表格列展示内容是封装到子组件Body中的。组件Body会先循环渲染表格的行数据,每一行下面包含一个BodyRow子组件
  • BodyRow子组件,行数据会进行循环单元格数据,而单元格的内容封装在Cell子组件中。
  • Cell单元格组件中,结合columns中的dataIndex确定最终回显的值。

      其中单元格的标签会根据传入的component的值不同,使用不同的标签,默认为td,表头thead传入的为tr。

component: Component='td',
......return (
<Component {...componentProps}>    {appendNode}
    {mergedChildNode}
</Component>);

Table组件比较复杂,功能比较丰富,组件的颗粒度也很细,我研究columns和dataSource就花了不少时间,更多的功能,后面再慢慢探索吧。

总结

多看一些优秀的项目源码,可以帮助拓展开发思路,提升技术设计思维。

现在有Antd等优秀的UI组件库,好像是不用重复造轮子了。但是奔着学习的目的,去开发一套UI组件还是可以帮助提升技术的。当然这些都是给初级开发者的建议,大佬们,大佬们的技术能力,我还在努力追赶。

轻松一笑

来自朋友的故事的衍生篇

聚餐,来两盘土豆丝,为什么是土豆丝,因为便宜;为什么两盘,因为一盘不够。


目录
相关文章
|
10天前
|
前端开发 JavaScript 开发者
前端开发中的组件化设计与性能优化
【10月更文挑战第7天】前端开发中的组件化设计与性能优化
21 0
|
2月前
|
JavaScript 前端开发 开发者
Vue.js 框架大揭秘:响应式系统、组件化与路由管理,震撼你的前端世界!
【8月更文挑战第27天】Vue.js是一款备受欢迎的前端JavaScript框架,以简洁、灵活和高效著称。本文将从三个方面深入探讨Vue.js:响应式系统、组件化及路由管理。响应式系统为Vue.js的核心特性,能自动追踪数据变动并更新视图。例如,通过简单示例代码展示其响应式特性:`{{ message }}`,当`message`值改变,页面随之自动更新。此外,Vue.js支持组件化设计,允许将复杂界面拆分为独立且可复用的组件,提高代码可维护性和扩展性。如创建一个包含标题与内容的简单组件,并在其他页面中重复利用。
68 3
|
10天前
|
前端开发 安全 测试技术
前端组件化有什么优势?
【10月更文挑战第4天】
15 1
|
12天前
|
前端开发 JavaScript 开发者
深入解析前端开发中的模块化与组件化实践
【10月更文挑战第5天】深入解析前端开发中的模块化与组件化实践
18 1
|
29天前
|
前端开发 开发者 UED
前端只是切图仔?来学学给开发人看的UI设计
该文章针对前端开发者介绍了UI设计的基本原则与实践技巧,覆盖了布局、色彩理论、字体选择等方面的知识,并提供了设计工具和资源推荐,帮助开发者提升产品的视觉与交互体验。
|
2月前
|
开发者 C# Android开发
明白吗?Xamarin与Native的终极对决:究竟哪种开发方式更适合您的项目需求,让我们一探究竟!
【8月更文挑战第31天】随着移动应用开发的普及,开发者面临多种技术选择。本文对比了跨平台解决方案Xamarin与原生开发方式的优势与劣势。Xamarin使用C#进行跨平台开发,代码复用率高,可大幅降低开发成本;但因基于抽象层,可能影响性能。原生开发则充分利用平台特性,提供最佳用户体验,但需维护多套代码库,增加工作量。开发者应根据项目需求、团队技能和预算综合考量,选择最适合的开发方式。
90 0
|
2月前
|
JavaScript 前端开发 开发者
决战前端之巅!Element UI与Vuetify谁才是Vue.js组件界的霸主?一场关于颜值与实力的较量!
【8月更文挑战第30天】本文对比了两款热门的Vue.js组件库——Element UI与Vuetify。Element UI由饿了么团队打造,提供多种高质量UI组件,设计简洁大方。Vuetify基于Material Design规范,支持Vue.js 2.0及3.0版本,具备前瞻性。两者均涵盖表单、导航、数据展示等组件,Element UI配置选项丰富,而Vuetify则提供了更深层的样式定制功能。开发者可根据项目需求及个人偏好选择合适的组件库。
167 0
|
3月前
|
编解码 前端开发 UED
UI/UX设计在前端开发中的重要性
【7月更文挑战第27天】综上所述,UI/UX设计在前端开发中具有不可替代的重要性。它们不仅决定了产品的视觉呈现和交互体验,还影响了用户的满意度、品牌形象、转化率和技术创新等多个方面。因此,在前端开发过程中,我们应该高度重视UI/UX设计的作用和价值,与设计师紧密合作共同打造出优秀的产品。
|
3月前
|
前端开发 JavaScript API
现代前端开发中的Web组件化设计与实践
在现代前端开发中,Web组件化已经成为了一个关键的设计思想和实践方法。本文探讨了Web组件化的概念、优势以及如何在实际项目中进行设计和应用。通过分析实例和最佳实践,展示了如何利用组件化开发提升前端开发效率和代码可维护性,同时也解决了在大型项目中常见的代码重用和团队协作问题。
|
3月前
|
前端开发 API
前端框架与库 - Material-UI组件库
【7月更文挑战第20天】Material-UI 是一个基于 React 的 UI 组件库,它遵循 Google 的 Material Design 设计规范,提供了丰富的预构建组件,极大地简化了前端开发过程。本文将深入浅出地介绍 Material-UI 的常见问题、易错点及如何避免这些问题,并附带代码示例,帮助你更好地掌握 Material-UI 的使用技巧。
114 0