前言
上周优化了个跑马灯,原因是跑马灯的长度太长了,每个item的节点比较多,所以即使限制最多只有50个item,也还是很长很长,有多长接口是什么可以看看下面


怎么优化呢?看看之前的跑马灯
优化前的写法



之前的写法很简单,其实就是陈涉世家翻译及原文让很长很长的class=”animate”的div在l接口测试用例设计ottery-person-wrapper
中滚动。用的是css 中的animation属性。
用animation虽然好,但是不能控制跑马灯的长度,即我不想让50个item一起滚动,最好是让只需要出现在屏幕中的item滚动就好了。于是就将滚动改成了item为绝对定位,然后利用transform来改变位置,然后利用transition来实现动画的过渡。
优化后的写法

可以看到没有那么多的item节点了,这是怎么办CSS到的呢?
- 首先获取lottery-person-wrapper的宽度
this.animationWrapperWidth = this.$refs.animateWrapper.clientWidth;
- 然后再让一个item出现在跑马灯中。
mounted() { this.$nextTick(() => { this.animationWrapperWidth = this.$refs.animateWrapper.clientWidth; this.emitItem(); }); }
- 看看emit是怎么写的
首先需要知道
- swiperUserList是从接口获取到的列表
- swiperUserListShow是在template中遍历的列表

我们先拿出swiperUs接口erList中的第一动画个item,然后再把item放入swiperUserList的尾部,让swiperUserList始终保持50个item。
然后,再把这个item深拷贝放入到swiperUserListShow中,为什么要深拷贝是因为,不希望swiperUserListShow的item与swiperUserList中的item出现引用的关系,否则会十分混接口卡乱。
给每一个item添加了一个id是为了作为遍历时独一无二的key

接下来则是要获取该item的宽度clientWidth,然后计算出该item的尾部出现的时间endShowTime,以及该i接口文档tem完全走完消失的时间disappearTime
在该item尾部出现的时候,就让下一个item push到swiperUserListShow中,使其出现在跑马灯中,在该item完全跑完消失的时候就让这个item从swi动画片猫和老鼠perUserListShow中剔除。
emitItem() { if (!this.isShow) { return; } let swiperUser = this.swiperUserList.shift(); this.swiperUserList.push(swiperUser); this.swiperUserListShow.push( Object.assign({}, { ...swiperUser, id: this.swiperId }) ); this.swiperId += 1; this.$nextTick(() => { let elm = this.$refs.swiperUserList[this.swiperUserListShow.length - 1]; let elmWidth = elm.clientWidth || 0; let disappearTime = (elmWidth + this.animationWrapperWidth) / 60; let endShowTime = elmWidth / 60; let moveItem = this.swiperUserListShow[this.swiperUserListShow.length - 1]; elm.style.transition = `transform ${disappearTime}s linear`; elm.style.transform = 'translate(-100%,-50%)'; // this.clearTimer(moveItem) moveItem.endShowTimer = window.setTimeout(() => { clearTimeout(moveItem.endShowTimer); moveItem.endShowTimer = null; this.emitItem(); }, endShowTime * 1000); moveItem.disappearTimer = window.setTimeout(() => { clearTimeout(moveItem.disappearTimer); moveItem.disappearTimer = null; this.swiperUserListShow.shift(); }, disappearTime * 1000); }); },
基本上就已经实现了。
为什么说是基本接口卡?
因为有两个坑。
看看坑
第一个是我们用了setTimeout,在我们将页面切到后台的时候,setTimeout里的代码是挂起的,不会执行,但是页面上的动画还是会继续执行的
elm.style.transition = `transform ${disappearTime}s linear`; elm.style.transform = 'translate(-100%,-50%)';
所动画制作软件以,为了解决这个bug,需要监听是否切出切入后台,切到后台则清除所有setTimeout和清空swiper仓鼠饲养八大禁忌UserListShow列表,切回页面,再重新执行emitItem。
mounted() { this.$nextTick(() => { this.animationWrapperWidth = this.$refs.animateWrapper.clientWidth; this.emitItem(); }); // 处理退出前台,跑马灯还在跑的问题,隐藏就是直接清空展示列表 document.addEventListener('visibilitychange', () => { const isShow = document.visibilityState === 'visible' this.handleSwiperListShow(isShow); }); }
methods: { // 处理跑马灯展示列表和清除计时器 handleSwiperListShow(isShow) { if (isShow) { this.emitItem(); } else { this.swiperUserListShow.forEach((item) => { clearTimeout(item.endShowTimer); clearTimeout(item.disappearTimer); }); this.swiperUserListShow = []; } }, }
第二个坑是我们使用了clientWidth来获取item的宽度,当我们页面中有tab的时候,并且跑马灯在某个tab下,然后当前v-show是激活的是其他tab,则会导致跑马灯被隐藏,则获取不到item的宽度,这时的c动画制作软件lientWidth的值为0.导致计算出来的endShowTime的值为0,则会导致疯狂执行settimeout里面的内容
为了解决这个bug则需要在父组件中传入仓鼠饲养八大禁忌isShow来判断跑马灯这个页面是否被隐长沙市疫情最新情况藏
props: { isShow: { type: Boolean, default: false }, }
然后监听isShow
watch: { // 处理tab选项卡隐藏抽奖模块,获取不到item clientWith的问题,隐藏就是直接清空展示列表 isShow(newVal, oldVal) { this.handleSwiperListShow(newVal) } },
至此,优化过程就到此完美结束了。
其实还有个比较简单的优化方法,但是不适陈思思用于我这个场景,但是也分享一下。
就是依然使用css的animation动画属性,然后使用an接口测试用例设计imationEnd的监听事件,

其他优化方案
当监听到结束的时候,利用v接口测试-if把仓鼠饲养八大禁忌当前跑马灯销毁,然后就往swiperUse长生十万年rListShow中push两个item,再生成展示跑马灯,又实现animation动画,这样是一个实现起来十分方便的方案,但是由于同一时刻只有我们push的item数,而且需要跑完才继续展示下两个,会留下一片空白,就有的不连贯的感觉,所以不使用这种长生十万年方案仓鼠饲养八大禁忌。

评论(0)