使用Element ui 组件库中
Upload组件,发现上传文件列表的增加,删除过渡效果可以优化。记录个人实际修改方案,仅供需要参考,欢迎留言分享更优秀的修改方案。
直接对Vue过渡的两种场景分析:enter/leave
现状
目前使用的过渡效果样式
过渡效果展示
list-type="text"
- enter
在Y轴向下移动渐显
整体过渡体验ok👌
- leave
在Y轴向上移动渐隐
删除文件过渡完后会有一个空白(被删除元素的大小)
然后后面的列表元素直接上移,无过渡的抖动效果。如果是最后一个文件删除,则外层容器边界也有明显的抖动效果,体验不好×。
如果删除的是第一个文件,整体过渡同上,但是列表元素上移后还会有一个下移的过渡(很是疑惑❓)。
这个下移距离只有 5px
list-type="picture" 过渡效果同上、list-type="picture-card",list-type="picture-card" 为inline-block 内联结构,所以删除第一个文件后没有下移的过渡,其他过渡效果同上。
问题解析
- 删除第一个文件过渡完后还会下移
原因是 list-type="text" 展示类型,每个元素自带上边距 5px,但是列表的第一个另外设置成 10px,当删除第一个文件后,需要进行重排,需要对 first-child 在下移 5px,并且列表元素直接设置了 transition 所以有明显的下移过渡。
去掉列表元素自带的 transition 样式,可去掉后续的一个过渡效果。
- 但是还会有一个下移问题,只不过直接下移
5px,比较不明显,可以去掉first-child的样式
直接把外边距加到列表容器上。这个样式主要是为了跟上传按钮间隔 10px
这样处理完,删除过渡后不会有下移的一个效果。【优化了一个 niceo( ̄▽ ̄)d】
- 但是,删除过渡完有一个空白,这个效果也很丑,整体不够顺滑。
这一个问题优化,我们接着来说
一种可以通过 height 去设置收缩效果达到顺滑效果,但是height 不固定,没法直接通过height过渡,可使用max-height 作为替代。
这时候有一个问题,max-hieght 必须比height大,否则删除过渡的时候会截断内容,显得更加奇怪了。同时,如果max-height设置特别大,最好速度快一点,否则会有一小段时间没效果(在等待max-height减少),考虑这个我就没实现这个问题,想尝试的可以自己加一下。
我用了第二种方案,vue的列表过渡【传送门】,提供了 v-move 的样式,会在元素的改变定位的过程中应用,删除一个列表元素后,后续元素可以顺滑的移动,而不是直接上移。
enter 过渡不变,只对leave过渡调整。
删除文件还是在Y轴上移渐隐
但是会发现列表后续的文件会一起平滑的上移
这时候就不会有一个空白展示
重点: leave-active 需要设置 position: absolute,才能达到实现 v-move 效果,同时,由于设置position: absolute,但并为指定 top、left,所以要保证看到删除文件的过渡效果,容器需要指定position: relative,否则删除文件就看不见。
如果未指定position: relative,删除文件消失(脱离原来文档流位置),后面的文件平滑上移,但是看到有一块空白。
这个问题就是 position: absolute 的定位问题。如果只给元素指定了absolute,未指定left/top/right/bottom。此时absolute元素的左上角定位点位置就是该元素正常文档流里的位置。
到这里,感觉整个过渡已经不错了
但是,使用Performance面板捕捉后,发现删除文件后(过渡效果同上),但是能够比较清楚的看到列表溢出容器。
解决这个溢出展示,最简单的给容器加个溢出隐藏overflow: hidden。
现在删除后,没有溢出效果。
但是,由于容器的高度还是在过渡效果结束前就改变了。原因就是因为设置position: absolute删除元素脱离了文档流,导致容器高度改变。
所以,这个过渡效果在列表元素高度比较大的时候,也是需要在进一步优化的。
list-type=picture-card 可以使用第二种方案(列表使用内联结构)
接下来是第三种方案,css过渡样式 + js钩子函数的组合使用,v-enter 保持不变(css过渡),v-leave 使用js钩子实现过渡,参考collapse-transition实现,在v-leave 获取删除元素的实际高度,并赋值给元素内联样式style.height,通过设置style.height=0实现height的过渡效果。这样,删除文件后续的列表元素也都会自动上移,不会出现第二种方案的问题。
v-enter 过渡css样式保留,删除v-leave 过渡css样式删除
注入js钩子函数
before-leave 获取删除元素实际的高度,设置内联样式style.height,并缓存内边距、溢出策略,
leave 钩子添加过渡样式类,并设置删除元素内联样式style.height=0,开启height过渡效果,并设置溢出策略overflow=hidden
after-leave 钩子删除过渡样式类,还原删除元素内边距、溢出策略
删除元素height高度过渡效果,没有上述出现问题【这才是最想要的效果】
这样不需要考虑作用于插槽自定义渲染列表的高度问题,完美【Perfect】!!!
最后,如果list-type=picture-card是,文件列表是内联元素,如果删除还是用height过渡(垂直方向),就有点奇怪了,应该在水平方向进行过渡。没错,就是width过渡,稍微修改一下js钩子就可以了。
before-leave 钩子
leave 钩子
after-leave 钩子
以上就是 Upload 优化的个人实际修改记录。第一种、第二种方法如果有解决方法,欢迎留言,我也会自己在尝试一下。
总的来说最好的过渡体验就是height过渡。如果扩展这个组件作为业务组件,直接限制好列表元素的高度,其实是最快最方便的。