image.png
介绍
写这篇文章的起因是作者不久前经历了一次项目整体ui组件库的替换, 本以为更换ui组件库只是改改样式并且改几处写法就行了, 但真正经历了才知道这里面遇到的问题还真是丰富多彩, 全程做下来我一共总结了21种问题类型, 希望哪一天你也有类似’需求’的时候可以找出来这篇文章看一看。
我经历的场景是公司内部研发了新的组件库, 新组件库大部分的’使用方式’和’设计理念’与旧组件库是一致的, 并且是公司内部的库所以不方便直接截图举例子, 文章里我就用antd来类比展示我遇到的问题, 顺带一提ts真香
在更换组件库时立了大功, 很多问题都是开发人员很难直接监测到的只能靠 ts
。
一: 属性的变化
属性被删除 (ts可标红
)
比如 button
组件之前有一个 textType
用来设置按钮的定制样式, 但是在新的组件库中被删掉了, 这些旧的特殊样式需要找ui同学确认是否保留。
新增属性
弹出框新增autoFocus
属性, 是否默认聚焦第一个可聚焦元素,如果组件库使用新增属性是为了替代某个旧属性的话, 那么替换时就需要找到属性间的对应关系。
属性改名 (ts可标红
)
比如弹框的确认按钮, 之前叫onConfirm
事件, 现在叫onOk
事件。
属性取值范围改变 (ts可标红
)
旧版组件button
的size
属性取值范围是 big mini small
, 新版组件库变成了default large
, 出现了三种属性对应两种属性的问题, 这个时候就要找ui同学来决定如何替换了。
二: 返回值的变化
类型变化 (ts可标红
)
我们的 日期组件
的 onchange
事件旧版返回的参数是被dayjs
处理过的对象, 直接可以针对这个值进行格式化的取值, 但是新版组件返回的是时间戳, 这种组件替换的时候需要我们主动为其转换一下格式:
旧版
onChange={(_: string[], date: Dayjs[]) => {
const startTime = date[0];
const endTime = date[1];
// ...
}}
新版
onChange={(_: string[], date: number[]) => {
if (date[0] && date[1]) {
const startTime = dayjs(date[0]);
const endTime = dayjs(date[1]);
// ...
}
}}
数量变化 (ts可标红
)
比如之前返回值是两个, 但是现在合成了一个对象里面的两个key返回给我们, 这时候要做一下结构再使用。
三: 限制条件的变化 (可能是bug)
InputNumber
数字输入框限制条件变了, 比如设置最小值为 1
, 当我输入0
的时候输入框会默认把值转为1
, 但是新版输入框竟然在我输入0
的时候没有把值转为1
, 这就导致接下来的所有操作都需要对是否为0进行校验。
这类问题才是最"要命的"
, 会导致原有变量的变化, 并且不实际操作一遍无法发现问题, 很多组件我们无法一一验证, 比如很多组件只在特定的情况下才会出现在用户的界面上, 这时候我们很容易漏测一些地方。
四: 显示层级的变化
不光是z-index
的问题, 每个组件所处的父级也会导致层级的不同, 比如我们前置有一个新人引导弹框
, 在更换新组建库后这个新人引导弹框
就被遮挡住了,
当新老组件库一起使用的时候, 老组件库的弹出框
组件, 与新组件库Tooltip提示框
配合使用的时候提示框无法显示。
这类问题不容易发现, 比如tooltip不显示这个问题, 对于一个不熟悉业务的人来说根本无法发现原本应该有个提示框
, 需要开发人员对业务很熟才能发现此类问题。
五: 组件联合使用的bug
我们有一种输入框
组件是可以插入一个 选择框
组件, 但是新版组件里面没有设置为这种插入组件:
旧组件
新组件
这种问题也比较棘手, 因为它并不会报错, 只是显示不一样, 这就导致只有真切的在页面上看到了这种错误才能发现。
六: 组件缺少
旧版组件库提供了懒加载组件
和 错误提示组件
, 但是新版的组件库没有这两个组件, 这时就需要联系负责的同学了, 看是否可以加上这两个组件, 如果不能加上只能自己亲手开发一个了, 这个问题也挺坑的, 无端增加了不小的工作量。
七: 兜底属性的改变
旧版组件库的table表格组件
会有默认的error错误图
和empty空值图
, 但是新版的没有这些图片, 需要我们手动的去添加。
比如弹出框
组件的onOk
事件如果不传入的话, 默认点击后是 “关闭弹框”, 但是新版组件里面不传就是没有任何操作效果, 这就需要之前没传onOk
事件的弹框每个都加一下。
这类问题也比较难发现, 因为并不会报错但是到处都有。
八: css属性的错乱 & 样式的差异
元素css属性被改变
比如table表格
组件每个td
的差异, 旧版组件里面没有为td
设置特殊的属性, 但是新版的表格组件为tb
设置了display: flex
属性, 这可把一堆样式都搞乱了, 简直惨不忍睹。
弹框组件
的footer
没有用div
之类的标签包住, 导致被父级的display: flex
影响, 比如我单独定义footer
为一个按钮的话, 这个按钮会被抻拉。
image.png
这类问题不好解决, 因为新的ui库的同学也不愿意改这种底层设计,而且新版的ui库已经有其他团队在使用了, 此时就需要我们自己写全局的css样式把它顶掉了。
整体样式未处理
新版组件库没有为组件添加box-sizing: border-box;
属性, 我当前的项目里也没有写*{box-sizing: border-box;}
, 就导致很多地方的样式都会有2px左右的偏移, 看起来十分别扭, 这类问题只能加css样式来解决了。
九: style || className 设置无效 (ts可标红
)
这个问题也是无意间发现的, 新版的ui库部分组件不接受style
参数了, 导致之前很多样式都不生效了, 但是我们也没法通过css的方式把样式注入进去, 这个挺无解的, 只能找相应的同学扩大一下新版ui组件的接收值范围。
十: 组件标签嵌套的改变
比如说弹出框
组件, 原本弹出框组件有两层div
包裹, 当我想要获取最外层的div
时就需要当前元素.parentNode?.parentNode
, 但是新版ui组件嵌套关系改了, 并且多嵌套了一层, 导致之前获取最外层元素的方法全部报错。
这里也让我们意识到, 最好不要写这种获取dom
的操作, 规范的模式应该是使用组件提供的方法获取组件的任何元素, 并且设计组件的时候也要把获取元素的方法导出来。
这种问题也不好发现, 只能是真的触发了获取父级的方法, 才能报错出来。
十一: 组件未做国际化
这个问题比较直观了, 当我们修改用户的语言时, 组件未根据我们选择的语言进行语言的变化, 这种功能发现之后让对应同学加一下就好了。
十二: 单独写的组件
有这样一种特殊情形, 在使用旧组件库
的时候, 某个组件的功能不能满足开发的需求, 当时的开发同学自己写了一个与组件库里的组件样式一模一样
的组件, 这个组件可能传参的规则是独立的, 无法与新的组件库无缝替换。
全局替换新组件库
后, 实际上上述的组件并没有被替换, 它还是保持旧版ui的样式, 因为它是单独编写的所以也不会报错, 但就是样式的改版需要我们单独为其编写一下, 也挺累人的。
这个问题也比较棘手, 因为实在是好难发现, 发现了修改起来也不是想象中的那样容易, 给我的启示就是以后进行使用组件库提供的组件进行开发, 自己写的组件无法进行更好的更迭。
十三: 样式变量的改变
比如旧组件库
里面定义红色分为red-01, red-02, red-03
几种类型的class名或者css变量, 分别表示深与浅的红色, 项目代码中也同样引入了旧组件库
提供的这些变量。
新组件库
里面也有一套自己的css 或者 scss 变量
, 命名与之前的完全不一样, 这导致比如我之前使用red-01
现在要改成color-obvious
, 像这种css变量
之间的对应关系可能需要写个函数循环比对, 但是不好的是他们的rgba
色值很可能完全不一样, 这就导致完全无法一一对应, 头疼不已。
这类问题只能一个一个的和ui对比了, 这里给我的启发就是哪怕一个小小的css
变量, 都需要一套完整的命名规范来设计才行。
十四: 循环出来的未知属性
上面我讲过了, 某些属性的取值范围可能变化了, 比如button
的size
属性的取值范围从 big mini small
, 新版组件库变成了default large
,这个是眼睛可以看到的, 但是有一种情况就惨了。
这里的举例写法:<button size={btSize}>ok</button>
这里面的btSize
是一个上层组件传递过来的变量, 这时ts可能会不报错但是它仍然会出现取值错误的问题。
要为这种情况专门写一下转换属性的方法比如:
let size = 'default';
if(btSize === 'small' ){
size = 'large';
}
这里用button举例是因为它比较简单, 实际情况比这个要难处理。
十五: 用法的拆分
比如弹出框
组件旧版组件库
导出一个Modal
, 可以直接<Modal/>
也可以Modal.info()
调用弹出框, 新版将它分为 modalFn
方法 与 Modal
组件。
之前的好多写法都要拆解替换, 每页都要检查不能遗漏。
十六: 旧ui 与新ui一起使用出错
当使用弹框组件
与下拉框组件
联合使用的时候, 如果点击下拉框组件唤出下拉框, 弹框组件
内部发生 ‘滚动’,下拉框组件
的下拉框还是停留在原位。
image.png
image.png
新旧组件库共同使用是存在风险的, 因为它们有可能根本就无法相互配合, 而且新组建的同学也不愿意修复这种 “问题”。
十七: 组件功能的抽离
比如旧版input
输入框组件发生错误的时候, 我们会传一个errortip='不可以为空'
这类的属性, input
就会出现红色的提示框与下方的提示信息, 但是新版组件库将这个功能完全放在<FormItem></FormItem>
这个标签里面, 也就是说如果我们想让input
框出现错误提示就要, 包一层<Form>
再包一层<FormItem>
, 但我们实际有很多地方并不适合这样做。
这种能力剥离的改版, 一般就是对业务理解的不同导致的, 如果诉求合理的话最好能把这个属性加回来。
十八: 整体类名的变化
css文件中, 这是一个必须解决的问题, 因为我们会写一些全局的css样式
, 比如某个组件内的某个元素必须30px
宽, 之类的属性吧, 但是更换组件库后组件的类名完全变了, 我们需要改掉这个名字。
js逻辑中, 有可能出现根据某个类型获取元素的情况, 这种情况最好也全局改一下。
十九: 代码库质量问题 例如ts报错
使用一套代码库的时候, 就好拉他的代码到本地看一看, 比如他是否逻辑严谨, 取值是否做了很多容错, 比如xxx.vvv.bbb
还是xxx?.vvv?.bbb
, 并且要看他的ts类型
是否完备, 比如写了一些any
或是在页面上放了很多/* eslint-disable */ 或者 // @ts-nocheck
那就建议谨慎接入把。
二十: 组件挂载dom不同
这是个挺别致的bug
, 主角是旧版弹框组件
, 比如在编辑页面
弹出是否要离开本页的提示, 用户页面路由发生变化这个弹框也就自动销毁了, 但是新版弹框组件
并不会销毁, 因为它默认是挂载在body
身上, 这就导致很多弹框关不掉
, 切换了页面这个弹框还是在屏幕上。
这种情况要不就找对应同学修一下, 要不就每个操作都主动加一个销毁当前弹框的操作。
二十一: 人力不足
人力是很关键的问题尤其是 新组件库
侧同学的人力, 很多问题被发现但又无法2日内解决, 这种情况很容易造成 “开发时间拉锯战”, 所以建议类似项目需要在新的ui库
有专门的开发同学专项支持的情况下进行替换, 我们与其配合完成这个艰巨的工作。
end
这次就是这样, 希望与你一起进步。
关于本文
作者:lulu_up
https://segmentfault.com/a/1190000040790162