vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue循环滚动列表

vue封装实现自动循环滚动的列表

作者:HXY999

在做数据大屏开发的过程中,经常出现需要对列表进行自动滚动的需求,所以本文就来为大家介绍一下如何利用vue封装一个自动循环滚动的列表吧

前言

在做数据大屏开发的过程中,经常出现需要对列表进行自动滚动的需求,为了个性化的实现各种需求,就封装了一个函数方法

解决方案

一、匀速自动滚动,并实现方法可对多个列表复用

思路:通过对ref的命名,来实现在方法中使用for循环来对多个列表生效

<template>
<div>
    <ul class="shiJianGaoJingContent_right" ref="scroll0">
        <li class="gaojing_info_list" v-for="(item, index) in scrollInfoList" :key="index">
        </li>
    </ul> 
</div>
</template>
<script>
export default {
  data() {
    return {
      scrollInfoList:[],
    };
  },
  methods: {
  // 列表自动滚动
    scrollFn() {
      let dataList = [];
      for (let i = 0; i < 1; i++) {
        let container = this.$refs["scroll" + i];
        let parentHeight = container.offsetHeight || 0;
        let scrollHeight = container.scrollHeight;
        let childHeight = container.firstChild.offsetHeight;
        let childCount = container.childNodes.length;
        let maxHeight = childHeight * childCount;
        let toHeight = container.scrollTop;
        let current = 0;
        dataList.push({
          parentHeight,
          scrollHeight,
          childHeight,
          childCount,
          maxHeight,
          toHeight,
          current,
          timer: null,
          timerMouseWheel: null,
        });
        function scrollCore() {
          {
            if (scrollHeight > parentHeight) {
              dataList[i].timer = setInterval(() => {
                let scrollStep = 1; // 每帧滚动的步长,可以适当调整
                if (container.scrollTop + parentHeight + 5 >= scrollHeight) {
                  // 如果滚动到底部,则将滚动位置重置为0
                  container.scrollTop = 0;
                  dataList[i].toHeight = 0;
                  dataList[i].current = 0;
                } else {
                  if (container.scrollTop < dataList[i].toHeight + dataList[i].childHeight) {
                    // 如果尚未滚动到目标位置,则逐帧更新滚动位置
                    container.scrollTop += scrollStep;
                  } else {
                    // 已滚动到目标位置,更新当前子项索引和子项高度
                    dataList[i].current = (dataList[i].current + 1) % dataList[i].childCount;
                    dataList[i].childHeight = container.childNodes[dataList[i].current].offsetHeight;
                    dataList[i].toHeight = container.scrollTop;
                  }
                }
              }, 2000 / 60); // 设置每秒更新60次,可根据需求调整
            }
          }
        }
        scrollCore()
      }
    },
  },
  mounted() {},
};
</script>

注:该方法在自动滚动到底部后会返回到顶部,循环滚动需要更改逻辑,在下方有循环的方法。

二、如何暂时关闭自动滚动

当我们想自己通过鼠标滚轮滚动该列表时,使该列表的自动滚动暂停,我们可以添加了一个名为mousewheel的事件监听器,以便在鼠标滚轮滚动时执行以下操作:

 container.addEventListener("mousewheel", () => {
          this.$nextTick(() => {
            clearInterval(dataList[i].timer);
            clearInterval(dataList[i].timerMouseWheel);
            dataList[i].toHeight = container.scrollTop;
            container.scrollTop = container.scrollTop;
            dataList[i].timerMouseWheel = setTimeout(() => {
              scrollCore()
            }, 3000)
          });
        });

三、如何彻底关闭自动滚动

在上面的方法中会一直无限的滚动下去,那么我们如果想停下具体看某一项要把自动滚动关闭掉呢,我们可以通过将关闭方法写在container的某个事件中,并将该事件派发给container来实现

// 监听关闭自动滚动的事件
container.addEventListener("closeScroll", () => {
          this.$nextTick(() => {
            clearInterval(dataList[i].timer);
            clearInterval(dataList[i].timerMouseWheel);
            toHeight = container.scrollTop;
            container.scrollTop = container.scrollTop;
          });
        });
// 完整代码
// 关闭列表自动滚动
    closeListScroll(container) {
      // 创建一个新的 自定义 事件
      const closeScroll = new Event("closeScroll");
      container.dispatchEvent(closeScroll)
    },
// 列表自动滚动
    scrollFn() {
      let dataList = [];
      for (let i = 0; i < 1; i++) {
        let container = this.$refs["scroll" + i];
        let parentHeight = container.offsetHeight || 0;
        let scrollHeight = container.scrollHeight;
        let childHeight = container.firstChild.offsetHeight;
        let childCount = container.childNodes.length;
        let maxHeight = childHeight * childCount;
        let toHeight = container.scrollTop;
        let current = 0;
        dataList.push({
          parentHeight,
          scrollHeight,
          childHeight,
          childCount,
          maxHeight,
          toHeight,
          current,
          timer: null,
          timerMouseWheel: null,
        });
        function scrollCore() {
          {
            if (scrollHeight > parentHeight) {
              dataList[i].timer = setInterval(() => {
                let scrollStep = 1; // 每帧滚动的步长,可以适当调整
                if (container.scrollTop + parentHeight + 5 >= scrollHeight) {
                  // 如果滚动到底部,则将滚动位置重置为0
                  container.scrollTop = 0;
                  dataList[i].toHeight = 0;
                  dataList[i].current = 0;
                } else {
                  if (container.scrollTop < dataList[i].toHeight + dataList[i].childHeight) {
                    // 如果尚未滚动到目标位置,则逐帧更新滚动位置
                    container.scrollTop += scrollStep;
                  } else {
                    // 已滚动到目标位置,更新当前子项索引和子项高度
                    dataList[i].current = (dataList[i].current + 1) % dataList[i].childCount;
                    dataList[i].childHeight = container.childNodes[dataList[i].current].offsetHeight;
                    dataList[i].toHeight = container.scrollTop;
                  }
                }
              }, 2000 / 60); // 设置每秒更新60次,可根据需求调整
            }
          }
        }
        scrollCore()
        container.addEventListener("mousewheel", () => {
          this.$nextTick(() => {
            clearInterval(dataList[i].timer);
            clearInterval(dataList[i].timerMouseWheel);
            dataList[i].toHeight = container.scrollTop;
            container.scrollTop = container.scrollTop;
            dataList[i].timerMouseWheel = setTimeout(() => {
              scrollCore()
            }, 3000)
          });
        });
        container.addEventListener("closeScroll", () => {
          this.$nextTick(() => {
            clearInterval(dataList[i].timer);
            clearInterval(dataList[i].timerMouseWheel);
            toHeight = container.scrollTop;
            container.scrollTop = container.scrollTop;
          });
        });
      }
    },

通过如上代码 我们就可以通过调用closeListScroll()方法来关闭列表自动滚动,如我们想要关闭ref=scroll0列表的自动滚动

// 示例 关闭ref=scroll0列表的自动滚动
// 某个方法中
clickSomeBtn(){
    ... //其他逻辑
    this.closeListScroll(this.$refs["scroll0"])
}

四、如何使自动滚动无限循环,使其头尾相连

思路:将一份数据复制为两份,在滚动到第二份与第一份重合的时候 立刻将滚动高度归位,这样从视觉效果上来看,就是无限滚动的效果 要实现这个效果,首先是我们需要将一份数据变为两份,最为简单的实现思路为直接将数据变为两份

<li class="gaojing_info_list" v-for="(item, index) in [...scrollInfoList,...scrollInfoList]" :key="index">

但是这样的话,我们需要对所有的列表都进行更改,容易遗漏,不符合封装思路
于是我就想着通过DOM方法直接在封装函数中进行操作,实现思路为

// 列表自动循环滚动
scrollFn() {
  let dataList = [];
  for (let i = 0; i < 1; i++) {
    let container = this.$refs["scroll" + i];
    console.log(container);
    // 使用 DOM 方法获取所有子元素
    let children = container.children;
    // 创建一个文档片段
    let fragment = document.createDocumentFragment();
    // 将子元素逐个重新插入到容器中
    for (let ind = 0; ind < children.length; ind++) {
      const child = children[ind].cloneNode(true);
      console.log(child, "child");
      fragment.appendChild(child);
    }
    // 一次性将文档片段添加回容器中
    this.$refs["scroll" + i].appendChild(fragment);
    let parentHeight = container.offsetHeight || 0;
    let scrollHeight = container.scrollHeight;
    let childHeight = container.firstChild.offsetHeight;
    let childCount = container.childNodes.length;
    let maxHeight = childHeight * childCount;
    let toHeight = container.scrollTop;
    let current = 0;
    dataList.push({
      parentHeight,
      scrollHeight,
      childHeight,
      childCount,
      maxHeight,
      toHeight,
      current,
      timer: null,
    });
    function scrollCore() {
      if (scrollHeight > parentHeight) {
        dataList[i].timer = setInterval(() => {
          let scrollStep = 1; // 每帧滚动的步长,可以适当调整
          if (container.scrollTop >= scrollHeight / 2) {
            // 滚动到与第一行重复的位置后 重置
            container.scrollTop = 0;
            dataList[i].toHeight = 0;
            dataList[i].current = 0;
          } else {
            if (
              container.scrollTop <
              dataList[i].toHeight + dataList[i].childHeight
            ) {
              // 如果尚未滚动到目标位置,则逐帧更新滚动位置
              container.scrollTop += scrollStep;
            } else {
              // 已滚动到目标位置,更新当前子项索引和子项高度
              dataList[i].current =
                (dataList[i].current + 1) % dataList[i].childCount;
              dataList[i].childHeight =
                container.childNodes[dataList[i].current].offsetHeight;
              dataList[i].toHeight = container.scrollTop;
            }
          }
        }, 2000 / 60); // 设置每秒更新60次,可根据需求调整
      }
    }
    scrollCore();
    container.addEventListener("mousewheel", () => {
      this.$nextTick(() => {
        clearInterval(dataList[i].timer);
        clearInterval(dataList[i].timerMouseWheel);
        dataList[i].toHeight = container.scrollTop;
        container.scrollTop = container.scrollTop;
        dataList[i].timerMouseWheel = setTimeout(() => {
          scrollCore();
        }, 3000);
      });
    });
     container.addEventListener("closeScroll", () => {
          this.$nextTick(() => {
            clearInterval(dataList[i].timer);
            clearInterval(dataList[i].timerMouseWheel);
            toHeight = container.scrollTop;
            container.scrollTop = container.scrollTop;
          });
        });
  }
}

以上就是vue封装实现自动循环滚动的列表的详细内容,更多关于vue循环滚动列表的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文