Vue2 实现一个无缝循环滚动的列表

前言

导师让我封装一个 无缝循环滚动的组件,要求是不能用插件,第三方库,最多只能用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 吗?欢迎交流

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值