13

(总结)项目经历一次更换ui组件库才知道的事: 共21种问题类型

image.png

介绍

     写这篇文章的起因是作者不久前经历了一次项目整体ui组件库的替换, 本以为更换ui组件库只是改改样式并且改几处写法就行了, 但真正经历了才知道这里面遇到的问题还真是丰富多彩, 全程做下来我一共总结了21种问题类型, 希望哪一天你也有类似'需求'的时候可以找出来这篇文章看一看。

     我经历的场景是公司内部研发了新的组件库, 新组件库大部分的'使用方式'和'设计理念'与旧组件库是一致的, 并且是公司内部的库所以不方便直接截图举例子, 文章里我就用antd来类比展示我遇到的问题, 顺带一提ts真香在更换组件库时立了大功, 很多问题都是开发人员很难直接监测到的只能靠 ts

一: 属性的变化

属性被删除 (ts可标红)

     比如 button组件之前有一个 textType用来设置按钮的定制样式, 但是在新的组件库中被删掉了, 这些旧的特殊样式需要找ui同学确认是否保留。

新增属性

     弹出框新增autoFocus属性, 是否默认聚焦第一个可聚焦元素,如果组件库使用新增属性是为了替代某个旧属性的话, 那么替换时就需要找到属性间的对应关系。

属性改名 (ts可标红)

     比如弹框的确认按钮, 之前叫onConfirm事件, 现在叫onOk事件。

属性取值范围改变 (ts可标红)

     旧版组件buttonsize属性取值范围是 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

     我们有一种输入框组件是可以插入一个 选择框组件, 但是新版组件里面没有设置为这种插入组件:

旧组件
image.png

新组件
image.png

     这种问题也比较棘手, 因为它并不会报错, 只是显示不一样, 这就导致只有真切的在页面上看到了这种错误才能发现。

六: 组件缺少

     旧版组件库提供了懒加载组件错误提示组件, 但是新版的组件库没有这两个组件, 这时就需要联系负责的同学了, 看是否可以加上这两个组件, 如果不能加上只能自己亲手开发一个了, 这个问题也挺坑的, 无端增加了不小的工作量。

七: 兜底属性的改变

     旧版组件库的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变量, 都需要一套完整的命名规范来设计才行。

十四: 循环出来的未知属性

     上面我讲过了, 某些属性的取值范围可能变化了, 比如buttonsize属性的取值范围从 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
5.7k 声望6.9k 粉丝

自信自律, 终身学习, 创业者