vue组件实现列表自动无限循环的方法
作者:The ever Boy
最近刚好有个功能需要实现列表的无限循环滚动,这篇文章主要给大家介绍了关于vue组件实现列表自动无限循环的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
前述:
用过vue-seamless-scroll插件,手动滚动列表到底部出现了空白现象,某些表现不符合项目场景,故自己写了一个自己用的组件,如果有人需要可以直接拿去用,如有不足请指教勿喷!
主要功能:
- 列表自动无限循环滚动
- 鼠标移入停止滚动,移出继续滚动
- 待滚动内容高度未铺满并超过容器高度时不滚动
- 支持滚动速度、单次滚动时间间隔、单次滚动高度,三个参数控制
- 可自己手动滚动列表
效果图 :
组件代码:
<template> <div class="scroll-outer" ref="outer" @mouseover="onMouseover" @mouseleave="onMouseleave"> <div class="scroll-inner-box" ref="scrollBox"> <div class="scroll-item-box" ref="scrollItemBox"> <slot></slot> </div> <div v-if="showSecond" class="scroll-item-box"> <slot></slot> </div> </div> </div> </template> <script> export default { name: "my-auto-scroll", props: { list: { type: Array, default: () => [ { name: "张三1" }, { name: "张三2" }, { name: "张三3" }, { name: "张三4" }, { name: "张三5" }, { name: "张三6" }, { name: "张三7" }, { name: "张三8" }, { name: "张三9" }, { name: "张三10" }, ], }, speed: { type: Number, default: 0.1, }, //滚动作单步运动时的单纯运动距离 singleHeight: { type: Number, default: 0, }, //单步运动的时间间隔 waitTime: { type: Number, default: 0, }, }, data() { return { rafId: null, y: 0, showSecond: false, controleHeight: 0, }; }, watch: { list: { handler(newVal) { var that = this; this.$nextTick(() => { console.log(newVal); if (newVal && newVal.length > 0) { let scrollBox = that.$refs.scrollBox; let outer = that.$refs.outer; if (this.myReq) { cancelAnimationFrame(this.myReq); } // 开启动画 if (this.canRun()) this.reqAnimationFrame(); // this.reqAnimationFrame(); // 手动滚动到底部时滚动条重置到最上边,同时滚动盒子重置为top:0 outer.addEventListener("scroll", function () { if ( outer.scrollTop + outer.clientHeight + 4 >= outer.scrollHeight ) { outer.scrollTop = 0; that.y = 0; scrollBox.style.top = 0; } }); } }); }, deep: true, immediate: true, }, }, mounted() { window.addEventListener("resize", this.listenResizeFn); }, methods: { listenResizeFn() { cancelAnimationFrame(this.myReq); if (this.canRun()) this.reqAnimationFrame(); }, onMouseover() { clearTimeout(this.timer); cancelAnimationFrame(this.myReq); }, onMouseleave() { if (this.canRun()) this.reqAnimationFrame(); }, canRun() { let scrollItemBox = this.$refs.scrollItemBox; let scrollBox = this.$refs.scrollBox; let outer = this.$refs.outer; // 开启动画条件:滚动盒子(scrollBox)高度高于外层容器(outer)高度 if (outer.offsetHeight >= scrollItemBox.offsetHeight) { this.showSecond = false; outer.scrollTop = 0; this.y = 0; scrollBox.style.top = 0; return false; } else { this.showSecond = true; return true; } }, //获取dom元素的高度:content+padding+margin+border getComputedHeight(dom) { let computedStyle = getComputedStyle(dom); let computedHeight = dom.offsetHeight + parseFloat(computedStyle.marginTop) + parseFloat(computedStyle.marginBottom); return computedHeight; }, reqAnimationFrame() { //外层容器 let outer = this.$refs.outer; //滚动盒子 let scrollBox = this.$refs.scrollBox; //滚动盒子下边的第一个scroll-item-box, let scrollItemBox = this.$refs.scrollItemBox; //滚动速度 this.speed = this.speed > 1 ? 1 : this.speed < 0 ? 0.1 : this.speed; //取第一个scrollItemBox高度 let definedHeight = this.getComputedHeight(scrollItemBox); //持续滚动 this.y = this.y + this.speed; scrollBox.style.top = -this.y + "px"; //====添加滚动间隔控制====开始 if (this.singleHeight >= 20 && this.waitTime > 500) { if (this.controleHeight >= this.singleHeight) { cancelAnimationFrame(this.myReq); this.controleHeight = 0; this.timer = setTimeout(() => { if (this.canRun) this.reqAnimationFrame(); }, this.waitTime); return; } else { // 一次移动高度未达到指定距离继续执行动画 this.controleHeight += this.speed; } } //====添加滚动间隔控制====结束 //当滚动到第一个scroll-item-box高度时scrollBox重置为top:0,视觉上是无缝滚动 if (this.y >= definedHeight) { this.y = 0; } this.myReq = window.requestAnimationFrame(this.reqAnimationFrame); }, }, destroyed() { window.removeEventListener("resize", this.listenResizeFn); cancelAnimationFrame(this.myReq); if (this.timer) clearTimeout(this.timer); }, }; </script> <style lang="scss"> .scroll-outer { height: 100%; overflow-x: hidden; position: relative; &::-webkit-scrollbar { width: 0.3vw; } &:hover::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3); border-radius: 0.1vw; background-color: #295099; opacity: 1; // display: none; } &:hover::-webkit-scrollbar-thumb { opacity: 1; border-radius: 0.1vw; -webkit-box-shadow: inset 0 0 0.1vw rgba(0, 0, 0, 0.3); background-color: #0ba9ea; } } .scroll-inner-box { height: auto; position: absolute; width: 100%; top: 0; left: 0; } </style>
使用示例:
import autoScroll from "@/components/autoScroll";
<autoScroll :list="list" :speed="0.5" :waitTime="2000" :singleHeight="100"> <div class="t-item" v-for="(item,index) in list" :key="index"> <div class="tvalue" style="flex: 0 0 30%;">{{ item.jgjc }}</div> <span class="tvalue">{{ item.total||'--' }}</span> <span class="tvalue" style="color:#0FCBDE">{{ item.ypc||'--' }}</span> <span class="tvalue" style="color:#F15730">{{ item.zlz||'--' }}</span> <span class="tvalue" style="color:#17DB68">{{ item.zlwc||'--' }}</span> </div> </autoScroll>
使用注意:
- autoScroll容器默认是占外层容器宽高百分百,要自己在autoScroll外层加个容器
- 参数waitTIme和singleHeight同时存在,才能出现滚动动画间隔执行的效果
- 样式用了sass,如果有问题可以去掉或者导入sass
总结
到此这篇关于vue组件实现列表自动无限循环的文章就介绍到这了,更多相关vue列表自动无限循环内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!