1.需求
--官方文档 列表的排序过渡
不多说,官方文档已经写得很明白。
项目中需要实现的功能是,根据时间线展示数据,一年的数据分为12个月,每个月内不同指标的数据占比排序,有进度条,数值大小,百分比等。
每一个月的数据变化,代表着排序出现变化,所以用到了Vue的列表交换位置效果。
2.表现
一开始,其实没问题,很顺利的交换了位置,只要把每个月份的数据依次填充到list,数据驱动视图的改变,虽然交换的速度很快。
但是,这样直接展示数据,效果太差,没有逼格,产品觉得还可以做得更好,比如:
- 进度条的长度不要一下子就改变完成,要有一个过渡效果
好的,我加一个过渡效果,{transition-duration: .3s;}
- 数值的变化也需要一个变化效果,不要从10直接飙到100,得11,12,13,……,100
这是什么操作?一定要做么?能不能不做?好吧,我做!!!
怎么做呢?
月份的切换,设定为5秒切换一次。
5秒之内,不断的修改数据,对应的value从上一个月份自增到下一个月份,同样还是数据驱动视图刷新,css{transition-duration: .3s;}
都是多余的,删掉,OK!
然鹅,鬼畜出现了。
数据没问题,过渡效果棒棒的。
但是位置交换的时候,就跟发羊癫疯,又像帕金森,磕多了炫迈,停不下来。
WTF?
还能不能好好的搬砖?
3.分析
其实没什么好分析的,代码就这几行。
数据驱动视图刷新,肯定是数据更新造成的。
但是为什么数据更新会造成排序交换位置
出问题呢?
已经设定了5秒钟才交换一次位置。
找不到原因,就无法解决这个bug。
看来,还是得分析Vue的交换位置逻辑。
官方文档读了几遍,终于,找到了关键字:FLIP。
在Vue中,交换位置的时候,其实不是真正的交换位置,毕竟列表中大部分的DOM元素是重用的,只是文字节点内容改变。
而实现交换效果的逻辑是:
假设列表有4个元素,依次排列a,b,c,d。
当排序发生变化的时候,顺序为b,a,c,d。
通过el.getBoundingClientRect()
获得a元素和b元素的位置差,添加特定的class,这个class设定了元素的变形过渡时间:
.flip-list-move {
transition: transform 1s;
}
然后计算出位置差invert
,通过设定变形效果el.style.transform = translateY(${invert}px)
,造成a,b,c,d依然在旧的位置的效果,然后移除变形设置,el.style = ''
。
因为这时候a,b,c,d的数据已经交换完成,元素回归原位置,看起来就像是从旧的位置直接来到新的位置。
过程有4个:
- 数据交换,排序,通过
el.style.transform = translateY(${invert}px)
把交换后的数据设置成交换前的效果 - 添加缓动样式
flip-list-move
, - 移除变形,
el.style = ''
,元素开始回归原位,但是看起来是跑到新的位置,这是重点 - 交换完成,移除缓动样式
flip-list-move
结语
之前一直有使用Vue的过渡效果,但是从来没有分析过实现的逻辑,这次终于踩到了巨坑。
很是不幸!
通过这次的分析,算是掌握了新的知识,原来可以这么玩!
但是,WTF,这个需求该怎么做???
已实现的github demo
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。