<template>
    <el-dialog v-model="dialogVisible" :show-close="false" class="auto-dialog" @close="handleCloseDialog">
        <div class="dialog-scroll-wrapper">
            <el-table ref="tableRef" :data="tableData" class="dialog-table" :header-cell-style="getHeaderStyle"
                :cell-style="getCellStyle" height="500" @cell-mouse-enter="onCellMouseEnter"
                @cell-mouse-leave="onCellMouseLeave">
                <el-table-column type="index" label="序号" width="80" align="center" />
                <el-table-column prop="name" label="姓名" align="center" />
                <el-table-column prop="date" label="出生日期" align="center" />
                <el-table-column prop="education" label="学历" align="center" />
                <el-table-column prop="address" label="家庭地址" align="center" />
            </el-table>
        </div>

        <!-- 功能按钮 -->
        <div class="dialog-tools">
            <el-button size="small" type="primary" @click="toggleAutoScroll">
                {{ isAutoScrolling ? "关闭滚动" : "开启滚动" }}
            </el-button>
            <el-button size="small" type="primary" @click="handleCloseDialog">
                关闭弹窗
            </el-button>
        </div>
    </el-dialog>
</template>


<script lang="ts" setup>
import { ref, watch, nextTick, onBeforeUnmount } from "vue";

const props = defineProps({
    modelValue: { type: Boolean, default: false }
});
const emit = defineEmits(["update:modelValue"]);

/* ========== 状态变量(全部规范命名) ========== */
const dialogVisible = ref(false);              // 控制弹窗显示
const isAutoScrolling = ref(false);            // 是否正在自动滚动
const tableRef = ref<any>(null);               // 表格 ref
const isHoverPaused = ref(false);              // 鼠标悬停暂停滚动
let autoScrollTimer: any = null;               // 滚动定时器

/* ========== 表格数据(正常命名) ========== */
const tableData = ref([
    { name: '李明', date: '1990-03-12', education: '高中', address: '贵州省凯里市金泉路 32 号' },
    { name: '王芳', date: '1988-07-25', education: '研究生', address: '贵州省麻江县兴隆街 18 号' },
    { name: '赵强', date: '1995-01-08', education: '本科', address: '贵州省锦屏县民族大道 56 号' },
    { name: '刘婷', date: '1992-11-19', education: '研究生', address: '贵州省镇远县古城北路 99 号' },
    { name: '张伟', date: '1986-05-31', education: '本科', address: '贵州省三穗县新城南路 10 号' },
    { name: '周倩', date: '1998-09-14', education: '高中', address: '贵州省岑巩县文化路 45 号' },
    { name: '陈浩', date: '1993-02-20', education: '研究生', address: '贵州省施秉县人民西路 77 号' },
    { name: '黄敏', date: '1997-06-02', education: '本科', address: '贵州省凯里市玉屏大道 88 号' },
    { name: '吴刚', date: '1989-12-05', education: '研究生', address: '贵州省台江县环城北路 25 号' },
    { name: '杨帆', date: '1994-04-18', education: '高中', address: '贵州省雷山县民族大道 66 号' },
    { name: '李佳', date: '1996-08-20', education: '本科', address: '贵州省凯里市开元街 22 号' },
    { name: '唐峰', date: '1987-10-11', education: '高中', address: '贵州省黎平县文昌路 58 号' },
    { name: '冯雪', date: '1999-03-05', education: '研究生', address: '贵州省榕江县城北新区 101 号' },
    { name: '谢军', date: '1991-07-29', education: '本科', address: '贵州省从江县鼓楼大道 70 号' },
    { name: '罗霞', date: '1996-12-16', education: '研究生', address: '贵州省凯里市清江路 15 号' },
    { name: '胡凯', date: '1993-09-03', education: '本科', address: '贵州省黄平县东门大街 40 号' },
    { name: '蒋婷', date: '1994-06-22', education: '研究生', address: '贵州省施秉县中山中路 12 号' },
    { name: '秦俊', date: '1990-02-27', education: '高中', address: '贵州省丹寨县迎宾大道 60 号' },
    { name: '姚丽', date: '1998-05-14', education: '本科', address: '贵州省凯里市大十字商圈 3 号' },
    { name: '崔鹏', date: '1985-11-08', education: '高中', address: '贵州省三穗县解放路 7 号' },
    { name: '曾薇', date: '1997-03-30', education: '研究生', address: '贵州省麻江县和平社区 13 号' },
    { name: '田亮', date: '1992-04-07', education: '本科', address: '贵州省台江县凯旋路 90 号' },
    { name: '彭敏', date: '1995-10-21', education: '高中', address: '贵州省雷山县银屏路 29 号' },
    { name: '宋凯', date: '1989-06-15', education: '高中', address: '贵州省凯里市碧海南路 66 号' },
    { name: '魏娜', date: '1993-08-12', education: '本科', address: '贵州省施秉县文化广场 5 号' },
    { name: '顾强', date: '1991-07-01', education: '本科', address: '贵州省榕江县东门大道 17 号' },
    { name: '韩雪', date: '1998-01-26', education: '高中', address: '贵州省镇远县青龙洞街 44 号' },
    { name: '廖峰', date: '1987-09-30', education: '本科', address: '贵州省从江县和平路 99 号' },
    { name: '康琳', date: '1996-02-18', education: '高中', address: '贵州省黄平县人民路 120 号' },
    { name: '傅豪', date: '1999-07-09', education: '研究生', address: '贵州省凯里市机场大道 222 号' }
]);

/* ========== 监听父组件 v-model ========== */
watch(
    () => props.modelValue,
    (val) => {
        dialogVisible.value = val;
        if (val) resetScrollPosition();
    }
);

watch(dialogVisible, (val) => emit("update:modelValue", val));

/* ========== 工具:获取表格滚动 DOM ========== */
const getTableScrollDom = () => {
    return tableRef.value?.$el?.querySelector(".el-scrollbar__wrap") || null;
};

/* ========== 工具:样式 ========== */
const getHeaderStyle = () => ({
    backgroundColor: "#0d3666",
    color: "#fff"
});

const getCellStyle = () => ({
    backgroundColor: "#6f86d6",
    color: "#fff"
});

/* ========== 功能:打开弹窗时重置滚动位置 ========== */
const resetScrollPosition = async () => {
    await nextTick();
    const wrapper = getTableScrollDom();
    if (wrapper) wrapper.scrollTop = 0;
};

/* ========== 功能:开启/关闭自动滚动 ========== */
const toggleAutoScroll = () => {
    isAutoScrolling.value = !isAutoScrolling.value;
    isAutoScrolling.value ? startAutoScroll() : stopAutoScroll();
};

const startAutoScroll = () => {
    stopAutoScroll();
    autoScrollTimer = setInterval(() => {
        const wrapper = getTableScrollDom();
        if (!wrapper || isHoverPaused.value) return;

        // 到底部则重置到顶部
        if (wrapper.scrollTop + wrapper.clientHeight >= wrapper.scrollHeight) {
            wrapper.scrollTop = 0;
        } else {
            wrapper.scrollTop += 1;
        }
    }, 50);
};

const stopAutoScroll = () => {
    clearInterval(autoScrollTimer);
    autoScrollTimer = null;
};

/* ========== 鼠标事件 ========== */
const onCellMouseEnter = () => {
    isHoverPaused.value = true;
};

const onCellMouseLeave = () => {
    isHoverPaused.value = false;
};

/* ========== 关闭弹窗 ========== */
const handleCloseDialog = () => {
    dialogVisible.value = false;
    isAutoScrolling.value = false;
    stopAutoScroll();
};

/* ========== 离开组件清理定时器 ========== */
onBeforeUnmount(() => stopAutoScroll());
</script>

<style scoped>
/* 覆盖 el-dialog 最外层,去掉 inline 样式 */
.auto-dialog {
    position: relative;
}

/* 外层滚动区域 */
.dialog-scroll-wrapper {
    height: 500px;
    background: linear-gradient(180deg, #163e80 0%, #174086 100%);
    overflow-y: auto;
    scrollbar-width: none;
    /* Firefox 隐藏滚动条 */
}

/* ElTable 默认背景透明 */
.dialog-table {
    width: 100%;
}

/* 顶部右上角按钮区 */
.dialog-tools {
    position: absolute;
    top: 5px;
    right: 16px;
    z-index: 9999;
}

/* 去掉单元格下划线 */
:deep(.el-table__cell) {
    border-bottom: none !important;
}
</style>

建一个文件AutoScrollTable.vue

你把上面这份代码 直接保存成:src/components/AutoScrollTable.vue 就能用了,定义一个按钮绑定事件用于打开这个对话框;

最终效果:

在需要使用的地方添加如下按钮

<el-button size="small" type="primary" @click="() => isVisiable = true">打开</el-button>



<AutoScrollDialog v-model="isVisiable" />

引入:import AutoScrollDialog from 'xx/xx/xx/AutoScrollDialog.vue'并生命const isVisiable = ref(false)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐