前言
导师让我封装一个 无缝循环滚动的组件,要求是不能用插件,第三方库,最多只能用element ui。
那好,直接手撕一个无缝滚动列表好吧
效果
实现效果如下:另外封装的这个组件,通过 props 1,可以控制滚动速度、 2,控制鼠标移入滚动停止功能、3,控制滚动到底部是跳到下一页数据,还是本页数据无缝循环滚动,4,在父组件可以控制是丝滑切换数据还是 回到顶部再继续滚动
1698298242609
实现
由于比较懒,直接给出全部代码,也方便各位靓仔使用
实现思路:
在vue中如何复制一份列表出来呢且不能丢失绑定的事件,很简单使用slot插槽,使用两个插槽我们就拥有了两个列表
<div class="listScroll" ref="box">
<slot></slot>
<slot></slot>
</div>
实现思路参考了另一个大佬,下面是原文链接,感谢
原文链接:https://blog.csdn.net/ZuoZuoDangerou/article/details/123662676
1,封装组件
<template>
<div class="listScroll" ref="box">
<slot></slot>
<slot></slot>
</div>
</template>
<script>
export default {
name: "listScroll",
created() {},
props: {
// 控制动画滚动 速度
speed: {
default: 1,
type: Number,
},
// 控制 鼠标移入滚动停止功能
isMouseControl: {
default: true,
type: Boolean,
},
// 控制 滚动到底部是跳到下一页 还是无缝循环滚动
isNextPage: {
default: false,
type: Boolean,
},
// 控制 切换下一页是丝滑切换数据 还是回到顶部再滚动
// isSmoothSwitch: {
// default: true,
// type: Boolean,
// },
},
mounted() {
//在盒子内容高度小于可视高度时不滚动
// if (this.boxHeight < this.ele0.clientHeight) {
// this.start(this.height);
// this.setEvet();
// }
// else {
// this.isScroll = false;
// }
this.start(this.height);
// 根据props 控制鼠标移入功能
if (this.isMouseControl) {
this.setEvet();
}
},
computed: {
//第一个slot
ele0() {
return this.$refs.box.children[0];
},
//第二个slot
ele1() {
return this.$refs.box.children[1];
},
//盒子的可视高度
boxHeight() {
return this.$refs.box.clientHeight;
},
},
data() {
return {
height: 0,
isScroll: true,
};
},
methods: {
//鼠标移入停止滚动 移出继续滚动
setEvet() {
this.$refs.box.onmouseenter = () => {
this.isScroll = false;
// this.height = 0;
};
this.$refs.box.onmouseleave = () => {
this.isScroll = true;
this.$nextTick(() => {
this.start(this.height);
});
};
},
//滚动方法
start(height) {
this.ele0.style = `transform:translateY(-${height}px);`;
this.ele1.style = `height:${this.boxHeight}px;transform:translateY(-${height}px);overflow: hidden;`;
if (height >= this.ele0.clientHeight) {
// 判断滚动到底部是跳到下一页 还是无缝循环滚动
if (this.isNextPage) {
// 让父组件跳到下一页
this.$emit('nextPage', 'hello');
}else{
this.height = 0;
}
} else {
this.height += this.speed;
}
if (!this.isScroll) return;
window.requestAnimationFrame(() => {
this.start(this.height);
});
},
},
};
</script>
<style lang="less" scoped>
.listScroll {
overflow: hidden;
}
.hover {
overflow-y: auto;
}
.hide {
display: none;
}
</style>
2,封装组件的使用
<template>
<div class="scroll">
<list-scroll class="box" :speed="1" ref="listScroll" @nextPage="nextPageFn()">
<div class="list">
<div class="item" v-for="item in list" :key="item.group">
<span>{{ item.group }}</span>
<span>{{ item.bookNum }}</span>
</div>
</div>
</list-scroll>
<button @click="nextPageFn()">按我换页</button>
</div>
</template>
<script>
import ListScroll from "@/components/DtSrcollCopy2";
export default {
name: "scroll",
components: { ListScroll },
data() {
return {
list: [
{ group: "软件班1", bookNum: 1, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班2", bookNum: 2, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班3", bookNum: 3, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班4", bookNum: 4, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班5", bookNum: 5, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班6", bookNum: 6, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班7", bookNum: 7, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班8", bookNum: 8, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班9", bookNum: 9, sceneNum: 0, dutyRate: "88%" },
{ group: "软件班10", bookNum: 10, sceneNum: 0, dutyRate: "88%" },
],
// 控制 切换下一页是丝滑切换数据 还是回到顶部再滚动
isSmoothSwitch:false
};
},
methods: {
nextPageFn(data){
// 判断是否 丝滑切换数据
if(this.isSmoothSwitch){
this.list = [
{ group: "物理班1", bookNum: 1, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班2", bookNum: 2, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班3", bookNum: 3, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班4", bookNum: 4, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班5", bookNum: 5, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班6", bookNum: 6, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班7", bookNum: 7, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班8", bookNum: 8, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班9", bookNum: 9, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班10", bookNum: 10, sceneNum: 0, dutyRate: "88%" },
]
}else{
this.list = [
{ group: "物理班1", bookNum: 1, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班2", bookNum: 2, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班3", bookNum: 3, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班4", bookNum: 4, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班5", bookNum: 5, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班6", bookNum: 6, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班7", bookNum: 7, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班8", bookNum: 8, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班9", bookNum: 9, sceneNum: 0, dutyRate: "88%" },
{ group: "物理班10", bookNum: 10, sceneNum: 0, dutyRate: "88%" },
]
// 控制滚动回到头部 继续滚动
console.log('看看子组件 实例,能不能直接改子组件数据', this.$refs.listScroll.height);
this.$refs.listScroll.height = 0
console.log('看看子组件传来的数据',data);
}
console.log('看看list 改变了吗?',this.list);
}
},
};
</script>
<style lang="less" scoped>
.box {
// 这里的高度很关键,一旦这里的高度小于 可视窗口高度
// 就不再滚动了
height: 300px;
}
.list {
padding: 0 10px;
width: 300px;
.item {
display: flex;
justify-content: space-between;
padding: 5px 0;
cursor: pointer;
&:hover {
background-color: #95a5a6;
}
}
}
</style>
感触
本来导师让封装element 表格的,结果套上 element 的壳子,数据驱动不了一点视图,以前一直觉得 框架和组件库好用,现在反而成了枷锁了,感触颇深。有大佬能实现一个无缝滚动的 el-table 吗?欢迎交流