vue2 el-table使用css的方式实现列表自动滚动
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title></title>
<!-- 1. 引入Vue2 CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.common.dev.min.js" crossorigin="anonymous"></script>
<!-- 2. 引入Element UI样式和JS -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/element-ui/2.15.14/index.min.js" crossorigin="anonymous"></script>
<style>
/* 1. 外层容器 */
.table-wrapper {
width: 700px;
height: 300px;
overflow: hidden;
position: relative;
}
/* 2. 表头层:固定顶部 */
.table-header {
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 10;
}
/* 表头层:只显示表头,隐藏内容行 */
.table-header .el-table__body-wrapper {
display: none !important;
}
.table-header .el-table {
margin: 0 !important;
padding: 0 !important;
}
/* 3. 内容滚动层:独立滚动容器 */
.table-body-scroll {
position: absolute;
top: 41px;
left: 0;
width: 100%;
height: calc(100% - 41px);
overflow: hidden;
padding: 0 !important;
margin: 0 !important;
}
/* 4. 滚动内容容器:核心样式 */
.table-scroll-content {
display: flex;
flex-direction: column;
/* 核心动画:短延迟启动,保证首行显示+正常滚动 */
animation: table-scroll-up 20s linear infinite 0.1s;
}
/* 悬停暂停核心样式:优先级拉满 */
.table-body-scroll:hover .table-scroll-content {
animation-play-state: paused !important;
cursor: pointer;
}
.table-scroll-item .el-table {
border-top: none !important;
}
.table-scroll-item .el-table__header-wrapper {
display: none !important;
}
/* 消除表格body默认边距,首行顶格 */
.table-scroll-item .el-table__body-wrapper {
border-top: none !important;
}
@keyframes table-scroll-up {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(0, -50%, 0);
}
}
</style>
</head>
<body>
<div id="app">
<div class="table-wrapper">
<!-- 固定表头 -->
<div class="table-header">
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="id" label="序号" width="80" align="center"></el-table-column>
<el-table-column prop="name" label="告警类型" width="150" align="center"></el-table-column>
<el-table-column prop="area" label="告警区域" width="120" align="center"></el-table-column>
<el-table-column prop="time" label="告警时间" align="center"></el-table-column>
<el-table-column prop="status" label="处理状态" width="100" align="center"> </el-table-column>
</el-table>
</div>
<!-- 内容滚动层:绑定鼠标事件兜底 -->
<div class="table-body-scroll" ref="bodyScroll" @mouseenter="pauseScroll" @mouseleave="resumeScroll">
<div class="table-scroll-content" ref="scrollContent">
<!-- 第一份内容 -->
<div class="table-scroll-item">
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="id" label="序号" width="80" align="center"></el-table-column>
<el-table-column prop="name" label="告警类型" width="150" align="center"></el-table-column>
<el-table-column prop="area" label="告警区域" width="120" align="center"></el-table-column>
<el-table-column prop="time" label="告警时间" align="center"></el-table-column>
<el-table-column prop="status" label="处理状态" width="100" align="center"> </el-table-column>
</el-table>
</div>
<!-- 第二份内容(无缝衔接) -->
<div class="table-scroll-item">
<el-table :data="tableData" border style="width: 100%">
<el-table-column prop="id" label="序号" width="80" align="center"></el-table-column>
<el-table-column prop="name" label="告警类型" width="150" align="center"></el-table-column>
<el-table-column prop="area" label="告警区域" width="120" align="center"></el-table-column>
<el-table-column prop="time" label="告警时间" align="center"></el-table-column>
<el-table-column prop="status" label="处理状态" width="100" align="center"> </el-table-column>
</el-table>
</div>
</div>
</div>
</div>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
tableData: [
{ id: 1, name: '陌生人闯入', area: '区域1', time: '2026-03-17 10:01:23', status: '未处理' },
{ id: 2, name: '车辆违停', area: '区域2', time: '2026-03-17 10:02:45', status: '已处理' },
{ id: 3, name: '人员聚集', area: '区域3', time: '2026-03-17 10:03:12', status: '未处理' },
{ id: 4, name: '消防通道堵塞', area: '区域4', time: '2026-03-17 10:04:56', status: '未处理' },
{ id: 5, name: '翻越围栏', area: '区域5', time: '2026-03-17 10:05:34', status: '已处理' },
{ id: 6, name: '烟雾检测', area: '区域6', time: '2026-03-17 10:06:18', status: '未处理' },
{ id: 7, name: '声光异常', area: '区域7', time: '2026-03-17 10:07:05', status: '已处理' },
{ id: 8, name: '设备离线', area: '区域8', time: '2026-03-17 10:08:42', status: '未处理' },
],
tableScrollDuration: 20,
};
},
mounted() {
// DOM渲染完成后调整样式和动画
this.$nextTick(() => {
this.autoAdjustHeaderHeight();
this.setTableScrollDuration();
// 手动触发动画,确保滚动生效
const scrollContent = this.$refs.scrollContent;
if (scrollContent) {
scrollContent.style.animation = '';
setTimeout(() => {
scrollContent.style.animation = `${this.tableScrollDuration}s table-scroll-up linear infinite 0.1s`;
}, 100);
}
});
},
methods: {
// 动态调整滚动时长
setTableScrollDuration() {
const scrollContent = this.$refs.scrollContent;
if (!scrollContent) return;
const duration = Math.max(15, this.tableData.length * 2);
this.tableScrollDuration = duration;
scrollContent.style.animationDuration = `${duration}s`;
},
// 自动适配表头高度
autoAdjustHeaderHeight() {
const header = this.$el.querySelector('.table-header');
const bodyScroll = this.$refs.bodyScroll;
if (header && bodyScroll) {
const headerHeight = header.offsetHeight;
bodyScroll.style.top = `${headerHeight}px`;
bodyScroll.style.height = `calc(100% - ${headerHeight}px)`;
}
},
pauseScroll() {
const scrollContent = this.$refs.scrollContent;
if (scrollContent) {
scrollContent.style.animationPlayState = 'paused';
}
},
resumeScroll() {
const scrollContent = this.$refs.scrollContent;
if (scrollContent) {
scrollContent.style.animationPlayState = 'running';
}
},
},
});
</script>
</body>
</html>