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-tablestructure, the
el-scrollbar__viewcontains all items, while
el-scrollbar__wrapis a fixed‑height container. The directive obtains the
el-scrollbar__wrapelement, sets a timer, and repeatedly updates its
scrollTopvalue, 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
truethe scroll proceeds, otherwise it stops.
Wheel Event Logic
When the mouse leaves the list, the current
scrollTopof
el-scrollbar__wrapis saved to the variable so the timer can continue scrolling from that position.
Non‑Scrolling Logic
The directive compares the height of
el-scrollbar__viewwith the height of
el-scrollbar__wrap; scrolling only occurs when the content height exceeds the container height.
Source Code
File:
tableAutoScroll.ts <code>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;
});
},
};</code>The
createdhook initializes three variables: a timer reference, a scroll‑enabled flag, and the current scroll position. The
mountedhook reads an optional
delayoption to customize the scroll speed.
Usage
Place the directive file in your project.
Register the directive in
main.tsand optionally expose an
installfunction for batch registration.
<code>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]);
});
};</code>Apply the directive to an
el-table:
<code><!-- 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>
</code>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.
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.