el-table 实现表头置顶【干货满满】附源码

a)一般情况下,想要在 ElTable 上实现表头固定,滑动滚动条时希望表头常显,不被滚动条顶上去。这时候就需要给表格添加高度,但是这个高度需要提前确定好,不是很方便,表格上边一段距离不是固定的,常常需要动态去使用 css 的 calc 函数进行减法扣除。
b)百度一下,看了一下别人常用的做法是 position:sticky 粘性定位。我这里就想到封装了 mixins 作为插件来实现,当时目的也是达到了,后面测试出来发现种种原因导致事件绑定冲突就放弃这种写法。
c)最后直接想起来el-*-plus的固钉组件,(这里不用plus版本的组件,不便于移植)由于版本项目问题,我这里是抽离出来以vue2的方式实现。我这里选择的是vant-ui@2.x 的 sticky组件源码 粘过来修修改改也能用。
d)最后又去修改了el-table 的 表头部分(下面会显示修改内容),使用 sticky 组件二次包装了一下即完成预期效果。

在这里插入图片描述

e)接下来就是修改 table 的组件代码内容(结尾附 github 地址)

创建新文件和 table 同级让其继承table(./el-table/index.vue

<template>
  ...
  // 将原先 TableHeader 使用 affix 包装一下
  <affix :container="$el" :disabled="disabledAffix">
    <div
      v-if="showHeader"
      v-mousewheel="handleHeaderFooterMousewheel"
      class="el-table__header-wrapper"
      ref="headerWrapper"
    >
      <TableHeader
        ref="tableHeader"
        :store="store"
        :border="border"
        :default-sort="defaultSort"
        :style="{
          width: layout.bodyWidth ? layout.bodyWidth + 'px' : '',
        }"
      >
      </TableHeader>
    </div>
  </affix>
  ...
</template>

<script>
import Table from "./table.vue";
import affix from "./affix.vue";

export default {
  name: "ElTable",
  extends: Table,
  components: { affix },
  props: {
    data: { type: Array, default: () => [] },
    size: String,
    width: { type: [String, Number], default: "100%" },
    height: [String, Number],
    maxHeight: [String, Number],
    fit: { type: Boolean, default: true },
    stripe: { type: Boolean, default: true }, // 修改默认值
    border: Boolean,
    rowKey: [String, Function],
    context: {},
    showHeader: { type: Boolean, default: true },
    showSummary: Boolean,
    sumText: String,
    summaryMethod: Function,
    rowClassName: [String, Function],
    rowStyle: [Object, Function],
    cellClassName: [String, Function],
    cellStyle: [Object, Function],
    headerRowClassName: [String, Function],
    headerRowStyle: [Object, Function],
    headerCellClassName: [String, Function],
    headerCellStyle: [Object, Function],
    highlightCurrentRow: { type: Boolean, default: true }, // 修改默认值
    currentRowKey: [String, Number],
    emptyText: String,
    expandRowKeys: Array,
    defaultExpandAll: Boolean,
    defaultSort: Object,
    tooltipEffect: String,
    spanMethod: Function,
    selectOnIndeterminate: { type: Boolean, default: true },
    indent: { type: Number, default: 16 },
    treeProps: {
      type: Object,
      default: () => ({ hasChildren: "hasChildren", children: "children" }),
    },
    lazy: Boolean,
    load: Function,
    // 新增 一个 disabledAffix 状态
    disabledAffix: Boolean,
  },
};
</script>
table-header (./el-table/table-header.jsx)

文件中主要改动是 table 引用,被 affix 包装过之后,$parent 指向已经被改变。因此需要向上查找到父级 table。并将所有的 == this.¥parent.xxx== 修改为 this.table

export default {
  name: "ElTableHeader",
  methods: {
    ...,
    handleHeaderClick(event, column) {
      if (!column.filters && column.sortable) {
        this.handleSortClick(event, column)
      } else if (column.filterable && !column.sortable) {
        this.handleFilterClick(event, column)
      }
      // this.$parent 需要替换为 this.table
      this.table.$emit('header-click', column, event)
    },

    handleHeaderContextMenu(event, column) {
      // this.$parent 需要替换为 this.table
      this.table.$emit('header-contextmenu', column, event)
    },
    ...
  },
  computed: {
    // // table 被重写
    table() {
      let parent = this.$parent;
      while (parent && !parent.tableId) {
        parent = parent.$parent;
      }
      return parent;
    },
  },
};

使用方式(新增属性 disabled-affix )
参数说明类型默认值
disabled-affix是否启用 affixbooleantrue
<el-table :data="table.data" v-loading="table.loading" border stripe :disabled-affix="true" :header-cell-style="{ backgroundColor: '#efefef' }"
  :hidden-columns="table.hiddenColumns" @header-cell-dragend="headerCellDragend" @header-dragend="headerDragend"
  @table-ready="tableReady">
  <el-table-column align="center" type="index" label="#" />
  <el-table-column align="center" prop="name" label="Name" />
  <el-table-column align="center" prop="address" label="Address" />

  <el-table-column align="center" prop="tags" label="Tags">
    <template slot-scope="{ row, column: col }">
      <el-tag v-for="tag in row.tags" :key="tag" :type="tag.length > 5 ? 'success' : 'info'">{{ tag }}</el-tag>
    </template>
  </el-table-column>

  <el-table-column align="center" prop="date" label="Date" />

  <el-table-column align="center" label="Contorl">
    <template slot-scope="{ row, column: col }">
      <el-button type="text" size="mini">删除</el-button>
    </template>
  </el-table-column>
</el-table>

github example 地址 内容包括之前拖拽,列显示操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值