How to Build a Custom Vue3 Auto‑Scrolling Table Directive with Element‑Plus
This article explains how to create a custom Vue 3 directive for automatic scrolling of Element‑Plus tables, covering the underlying logic, handling mouse events, conditional scrolling, and integration steps with code examples, enabling developers to implement smooth list carousels without third‑party plugins.
Introduction
This tool is a Vue3 directive designed for the Element‑Plus UI library; it assumes a basic understanding of Vue3 directives.
Demo
Implementation Idea
First determine the required features:
Automatic list scrolling
Pause on mouse hover
Resume on mouse leave
Continue scrolling from the current position after wheel scroll completes
Do not scroll when the number of items is below a certain threshold
Scrolling Logic
By inspecting the el-table structure, the el-scrollbar__view contains all items, while el-scrollbar__wrap is a fixed‑height container. The directive obtains the el-scrollbar__wrap element, sets a timer, and repeatedly updates its scrollTop value, storing the value in a variable to keep it persistent.
Pause/Resume Logic
A boolean variable is used inside the timer; when the variable is true the scroll proceeds, otherwise it stops.
Wheel Event Logic
When the mouse leaves the list, the current scrollTop of el-scrollbar__wrap is saved to the variable so the timer can continue scrolling from that position.
Non‑Scrolling Logic
The directive compares the height of el-scrollbar__view with the height of el-scrollbar__wrap; scrolling only occurs when the content height exceeds the container height.
Source Code
File:
tableAutoScroll.ts interface ElType extends HTMLElement {
timer: number | null;
isScroll: boolean;
curTableTopValue: number;
}
export default {
created(el: ElType) {
el.timer = null;
el.isScroll = true;
el.curTableTopValue = 0;
},
mounted(el: ElType, binding: { value?: { delay?: number } }) {
const { delay = 15 } = binding.value || {};
const tableDom = el.getElementsByClassName('el-scrollbar__wrap')[0] as HTMLElement;
const viewDom = el.getElementsByClassName('el-scrollbar__view')[0] as HTMLElement;
const onMouseOver = () => (el.isScroll = false);
const onMouseOut = () => {
el.curTableTopValue = tableDom.scrollTop;
el.isScroll = true;
};
tableDom.addEventListener('mouseover', onMouseOver);
tableDom.addEventListener('mouseout', onMouseOut);
el.timer = window.setInterval(() => {
const viewDomClientHeight = viewDom.scrollHeight;
const tableDomClientHeight = el.clientHeight;
if (el.isScroll && viewDomClientHeight > tableDomClientHeight) {
const curScrollPosition = tableDom.clientHeight + el.curTableTopValue;
el.curTableTopValue =
curScrollPosition === tableDom.scrollHeight ? 0 : el.curTableTopValue + 1;
tableDom.scrollTop = el.curTableTopValue;
}
}, delay);
},
unmounted(el: ElType) {
if (el.timer !== null) {
clearInterval(el.timer);
}
const tableDom = el.getElementsByClassName('el-scrollbar__wrap')[0] as HTMLElement;
tableDom.removeEventListener('mouseover', () => (el.isScroll = false));
tableDom.removeEventListener('mouseout', () => {
el.curTableTopValue = tableDom.scrollTop;
el.isScroll = true;
});
},
};The created hook initializes three variables: a timer reference, a scroll‑enabled flag, and the current scroll position. The mounted hook reads an optional delay option to customize the scroll speed.
Usage
Place the directive file in your project.
Register the directive in main.ts and optionally expose an install function for batch registration.
import tableAutoScroll from './modules/tableAutoScroll.ts';
const directives: any = { tableAutoScroll };
export const install = (app: any) => {
Object.keys(directives).forEach(key => {
app.directive(key, directives[key]);
});
};Apply the directive to an el-table:
<!-- element list scroll directive plugin -->
<template>
<div class="container">
<el-table v-tableAutoScroll :data="tableData" height="300">
<el-table-column prop="date" label="时间" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="address" label="Address" />
</el-table>
<!-- delay: milliseconds per scroll -->
<el-table
v-tableAutoScroll="{ delay: 50 }"
:data="tableData"
height="300"
>
<el-table-column prop="date" label="时间" />
<el-table-column prop="name" label="名称" />
<el-table-column prop="address" label="Address" />
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
const tableData = ref<any>([]);
onMounted(() => {
tableData.value = Array.from(Array(100), (_, index) => ({
date: '时间' + index,
name: '名称' + index,
address: '地点' + index,
}));
});
</script>
<style lang="scss" scoped>
.container {
height: 100%;
display: flex;
align-items: flex-start;
justify-content: center;
gap: 100px;
.el-table {
width: 500px;
}
}
</style>The example demonstrates both parameter‑less and parameterized usage.
Conclusion
After building this tool, the author plans to develop additional Vue3 directives and publish them as an open‑source directive collection.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
