- Published on
- 约 1774 字
一次有很有意思的 Antd Table 排序失效问题排查经历
- Authors
- Name
- 小辉辉
问题背景
一天项目bug列表里多了两个表格排序无效的问题,刚刚看到的时候我还心里一抖,这个排序问题还是前几天刚刚调试好的呢,怎么又有问题了呢,而且bug说明上面清晰的截图让我不得不承认这个功能可能真的坏了。
于是马上打开测试的地址,奇怪的问题发生了,表格排序功能完全没有问题,又去试了下另外一个排序问题,也是功能正常。
这个时候我就不得不去测试电脑上面去看问题了,上去操作了一下,纳闷了,还真的有问题。具体表现为当我把第一行的数据拖拽到第二行后面时,上下行的数据是进行交换了,但是序号那一列还是显示为2、1,不是我们所希望的1、2。
这个时候我本人根据过往经验脑海里浮现出来的几种可能性如下:
- 测试浏览器版本的问题导致功能问题
- 测试本地开了代理,访问的不是最新版本的代码(以前老版本的确存在拖拽问题)
- 浏览器出bug了
- 项目代码真的有问题
排查过程
先是说下表格排序的实现方式:
我们在表格最左侧会提供一个拖拽列,在每列对应的单元格上面放置一个拖拽的图标,通过拖拽该图标来实现,拖拽功能的实现也比较简单,在表格最外层放置了react-dnd
的排序组件,表格的每行数据挂载上react-dnd
对外暴露的相关拖拽事件,在拖拽结束事件里实现表格数据顺序的调整,由此来实现整个完整的排序功能。
再来说下序号列对应的单元格实现逻辑,我们对表格每个单元格都做了自定义Cell
组件,每个Cell
组件都会返回Antd
自带组织好的props
和默认的children
属性,序号列因为不用自定义,所以我们都是直接拿children
值来使用。
后期为了优化Antd
表格的性能,我们对每个Cell
组件单元格包裹了一个React.memo
方法,在第二个参数里单独实现了每种情况的比较逻辑,里面就包括了序号列,根据className
值来判断是否属于序号列,如果是的话,比较props
属性里的某个逻辑,也就是这里埋下了问题隐患。
好了,接着按照上面的可能性逐一排查了。
先说下浏览器不兼容的问题,现确认了下测试的浏览器版本,是chrome 128版本,照理说这个版本已经是很新的了,不应该会有兼容性问题,而且我本地还是119版本的都没有问题,不应该会出现高版本不兼容的情况吧。
但是不管怎么说,找一个同样的浏览器版本,如果的确有问题那就好说了,虽然说觉得不是很合理,但是也算是一个最快的排查方式了。
找一个特定的谷歌浏览器版本可真不容易,中间都想要放弃了,最后花费了一个早上终于下载到了一个相同的离线版本,但是当我满怀期待的打开有问题的页面去验证排序功能的时候,结果也是正常,这个时候又蒙了。
到这里肯定可以确定不是浏览器版本原因了,于是又和测试沟通,我想着之前也遇到过谷歌的偶然bug,只要重启下浏览器就能排除,试了下看看也还是不行。这个时候想到测试最开始提供的一个很重要的信息,他说无痕模式下功能是正常的,一开始对这个没有怎么在意,因为很难把排序功能和缓存相关的问题联系在一起,而且也确认过测试和我访问的是同一个版本。
到了这里,上述可能性只能剩下代码问题了,结合上面提到的无痕模式正常,让我不得不怀疑是哪里出问题了。
根据上面的逻辑,我在Cell
组件memo
方法里打了个断点,发现测试电脑浏览器上的处理逻辑一直是返回true
,而我本地浏览器上面是有false
也就是需要更新的逻辑的。
此时,问题又来了,这个比较逻辑其实用到了props
里面的children
属性,而这个children
属性是来自Antd
表格自上而下传递下来的。顺着代码一步步往上找来源,终于发现了下面的这块逻辑:
if (a.lastFixed && a.fixed) {
return createElement('span', {className: 'antd-cell-content'}, value)
}
return createElement(Cell, {...props}, value);
那我本地其实走的是第一个if
分支,而测试浏览器上面走的是第二个分支,所以造成了memo
里的比较逻辑失效了,那么lastFixed
又是哪里改的呢?一路排查上去,发现这个值是在Antd
表格最外面context
那一层存储的,里面有一段专门计算方法赋值逻辑。
关于这个方法实现我就不说了,具体功能从名字上面也能看出一二。它代表这列是不是左侧最后的一个固定列,序号我们知道肯定要固定在最左侧的,那么常规情况下lastFixed
值肯定为true
了,而测试环境为啥就变成false
了呢?
这个时候脑海里浮现了无痕模式正常这一个线索,顿时知道了原因。我们的表格为了支持用户自定义,特意做一个一个列配置功能,通过配置可以实现列顺序调换,显示隐藏,固定列首、列尾功能。而且这些配置是实时存储在浏览器缓存里面的,于是去测试浏览器上面看了配置果然验证了我的猜测。
至此,问题终于排查结束。
结论
这个问题的解决经历虽然说浪费了很多时间,但是中间翻看Antd
的实现源码过程好歹是给了我一点点安慰。通过这次经历,我也有下面几点收获:
- 浏览器一般不会出现问题,尤其是高版本
- 遇到问题大胆假设之前还是得先试着去看去看页面结构、和问题有关的那块代码,因为很多假设往往都是错误的
- 有时候浏览器缓存不仅仅是代码层面的,还有可能是用户数据层面上的
Antd
单元memo
逻辑还是需要借助于比较靠谱的属性,借助于判断children
属性目前看来并不是一个很好的办法