vue3封装一个悬浮操作固定列表格组件(性能版)

发布于:2025-02-26 ⋅ 阅读:(11) ⋅ 点赞:(0)

设计给的理由:再不需要操作按钮列时想要table表格看到更多列信息

方案1:通过js控制并计算位置
方案2:使用css控制节约性能

表格组件

<template>
  <el-table
    :data="tableData"
    style="width: 100%"
    @row-mouseenter="handleMouseEnter"
    @row-mouseleave="handleMouseLeave"
  >
    <!-- 数据列 -->
    <el-table-column prop="date" label="Date" width="150" />
    <el-table-column prop="name" label="Name" width="120" />
    <el-table-column prop="sex" label="Sex" width="120" />
    <el-table-column prop="city" label="City" width="120">
      <template #default="{ row }">
        <div class="cell-content">
          {{ row.city }}
          <!-- 操作按钮容器 -->
          <div class="operation-overlay" :class="{ active: activeRow === row }">
            <el-button
              link
              type="primary"
              size="small"
              @click.stop="handleDetail(row)"
            >
              详情
            </el-button>
            <el-button
              link
              type="primary"
              size="small"
              @click.stop="handleEdit(row)"
            >
              编辑
            </el-button>
          </div>
        </div>
      </template>
    </el-table-column>
  </el-table>
</template>

<script lang="ts" setup>
import { ref } from "vue";
// 当前激活行
const activeRow = ref(null);
const tableData = ref([
  { date: "2023-01-01", name: "John", city: "New York", sex: "男" },
  { date: "2023-02-01", name: "Alice", city: "London", sex: "男" },
  { date: "2023-03-01", name: "Bob", city: "Tokyo", sex: "女" },
]);

const handleMouseEnter = (row) => {
  activeRow.value = row;
};

const handleMouseLeave = () => {
  activeRow.value = null;
};

const handleDetail = (row) => {
  console.log("详情操作", row);
};

const handleEdit = (row) => {
  console.log("编辑操作", row);
};
</script>

<style scoped>
/* 单元格内容容器 */
.cell-content {
  display: block;
  width: 100%;
  height: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  position: relative;
}

/* 操作按钮覆盖层 */
.operation-overlay {
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(2px);
  box-shadow: -5px 0 15px rgba(255, 255, 255, 0.9);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}

/* 激活状态 */
.operation-overlay.active {
  opacity: 1;
  pointer-events: auto;
}

/* 按钮样式优化 */
:deep(.operation-overlay .el-button) {
  margin-left: 0;
  padding: 0 5px;
  position: relative;
  z-index: 2;
}

/* 行悬停效果 */
:deep(.el-table__body tr:hover td) {
  background: #f5f7fa !important;
}

/* 最后一列特殊处理 */
:deep(.el-table__body td:last-child .cell) {
  overflow: visible;
  padding-right: 0 !important;
}
/* 动态宽度适配: */
.operation-overlay {
  min-width: 120px; /* 根据按钮总宽度设置 */
  justify-content: flex-end;
}
/* 性能优化版本(纯CSS实现): */
/* 使用纯CSS实现 */
:deep(.el-table__body tr:hover td:last-child .operation-overlay) {
  opacity: 1;
  pointer-events: auto;
}
</style>

效果图
悬浮前:

 

悬浮后:

点击操作后: