JS如何优雅的实现模块自动滚动展示

简介: 【8月更文挑战第22天】JS如何优雅的实现模块自动滚动展示

需求

这几天做一个大屏可视化项目时,遇到一个需求,当某区域出现滚动条时,让它循环滚动展示数据。
GIF 2022-12-13 9-17-04.gif
当然,作为一个优秀的开发,我们还可以优化一下:鼠标放上去的时候,停止自动滚动;鼠标移开区域,重新开始滚动。

实现

基本实现思路

实现功能之前,我们需要了解三个参数

  • 可视高度clientHeight
  • 滚动条距离顶部的高度scrollTop
  • 滚动区域高度scrollHeight

image.png
根据上图的信息,我们很容易实现滚动条的自动滚动逻辑:
scrollHeight 大于clientHeight时,元素需要滚动,scrollTop++;当scrollTop + clientHeight等于scrollHeight时,即元素滚动到底部,我们再让scrollTop等于0即可。
转换成代码:

// 获取滚动区域的DOM
let parentDom = document.getElementById("XXX")
// 判断是否有滚动条
if(parentDom.scrollHeight <= parentDom.clientHeight) return
// 如果滚动到底部,scrollTop = 0;
if (
  parentDom.scrollTop + parentDom.clientHeight ===
  parentDom.scrollHeight
) {
   
   
  parentDom.scrollTop = 0;
} else {
   
   
  // 滚动条自增
  parentDom.scrollTop++; 
}

当然,我们需要设置一个定时器,让这个逻辑重复执行。

const scroll = () => {
   
   
  // 上述代码
};
let timer= setInterval(scroll, 100);

至此,我们的基本思路就完成了。当我们项目中有多个这样需要滚动的区域时,我们应该将这个方法封装,进行复用。

代码封装与复用

我们以主流的vue为例,进行代码封装,最合适的方式应该是将其作为vue中的指令使用。

阅读以下教程,需要您具备vue指令基础知识,可以参考vue官网教程。

指令的基本结构

首先,我们创建scroll.js文件,写入指令的最基本结构

// 实现滚动条自动滚动功能
const directive = {
   
   
  inserted(el, binding) {
   
   
    ...
  },
};
export default directive

main.js中引入该文件

import Vue from "vue";
import App from "./App.vue";
import directive from "./change";

Vue.config.productionTip = false;
// 注册名为 scroll 的指令
Vue.directive("scroll", directive);
new Vue({
   
   
  render: (h) => h(App),
}).$mount("#app");

此时,我们创造了一个名为v-scroll的指令,我们直接使用

// App.vue
<template>
  <div id="app" v-scroll>
    // XXXXX这里是您的自定义html
  </div>
</template>

完善指令

结合我们最开始的实现思路,可以完善指令

// js实现动态变化的数字
const directive = {
   
   
  inserted(el) {
   
   
    //el就是绑定的dom对象
    if (!el) return;
    const scroll = () => {
   
   
      let parentDom = el;
      // 判断是否有滚动条
      if(parentDom.scrollHeight <= parentDom.clientHeight) return
      //判断元素是否滚动到底部(可视高度+距离顶部=整个高度)
      if (
        parentDom.scrollTop + parentDom.clientHeight ===
        parentDom.scrollHeight
      ) {
   
   
        parentDom.scrollTop = 0;
      } else {
   
   
        parentDom.scrollTop++; // 元素自增距离顶部
      }
    };
    let timer = setInterval(scroll, 100);
};
export default directive;

现在我们指令的功能就完成了。当然,它还有个缺陷,鼠标移入这个元素的时候不能自动停止,移开这个区域不能恢复自动滚动。我们只需要在dom上绑定onmouseenteronmouseleave事件即可。

inserted(el) {
   
   
      // .....
      let timer = setInterval(scroll, rate);
      el.onmouseenter = () => {
   
   
        clearInterval(timer);
        timer = null;
      };
      el.onmouseleave = function () {
   
   
        timer = setInterval(scroll, 100);
      };
    },
  },

指令传值

更优的,这个滚动速度我们还可以自定义,通过元素来传值。vue指令钩子函数的的第二个参数binding.value可以接受参数。

// App.vue
<template>
  <div id="app" v-scroll="100">
    // XXXXX这里是您的自定义html
  </div>
</template>

此时,binding.value的值就是100,我们进一步优化代码

    inserted(el, binding) {
   
   
      const rate = binding?.value ??   100;
      if (!el) return;
      const scroll = () => {
   
   
        // ...省略
      };
      let timer: any = setInterval(scroll, rate);
      el.onmouseenter = () => {
   
   
        clearInterval(timer);
        timer = null;
      };
      el.onmouseleave = function () {
   
   
        timer = setInterval(scroll, rate);
      };
    },

大功告成!!

看完有收获的话,来个一键三连吧!

相关文章
|
5天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
11天前
|
缓存 JavaScript 前端开发
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
JavaScript模块化开发:ES6模块与CommonJs的对比与应用
15 2
|
19天前
|
算法 JavaScript 前端开发
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
国标非对称加密:RSA算法、非对称特征、js还原、jsencrypt和rsa模块解析
90 1
|
1月前
|
存储 缓存 JSON
Node.js有哪些模块系统
【8月更文挑战第12天】Node.js有哪些模块系统
32 3
|
1月前
|
算法 JavaScript 前端开发
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
对称加密算法解析:DES、AES及其在`pycryptodome` 和 `crypto-js` 模块中的应用
88 1
|
1月前
|
JavaScript 前端开发
使用js,html,css实现歌词滚动的效果
使用js,html,css实现歌词滚动的效果
34 0
|
2月前
|
JavaScript 前端开发
node.js 导入导出模块(CommonJS模块化规范,ES6模块化规范)
node.js 导入导出模块(CommonJS模块化规范,ES6模块化规范)
31 1
|
2月前
|
监控 JavaScript 前端开发
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
|
2月前
|
JavaScript
【Node.js基础02】fs、path模块
【7月更文挑战第17天】
15 0
|
3月前
|
JavaScript 应用服务中间件 Apache
Node.js Web 模块
Node.js Web 模块
32 2