6.4 Element UI 中的 <el-table> 表格组件

一、 核心组成与基本结构

Element UI 的表格主要由以下几个核心部分构成:

  1. <el-table>: 表格的根容器,负责管理数据、选择、排序、分页集成等全局状态。
  2. <el-table-column> : 定义表格的一列。表格的列结构由一个或多个 <el-table-column> 组件定义。
  3. data : 传递给 <el-table>data 属性,是一个数组,数组中的每个对象代表表格中的一行数据。
  4. prop : <el-table-column>prop 属性,指定该列显示 data 数组中每个对象的哪个属性的值。
  5. label : <el-table-column>label 属性,定义该列的标题

最基础的示例:

复制代码
<template>
  <el-table :data="tableData" style="width: 100%">
    <el-table-column prop="date" label="日期" width="180"></el-table-column>
    <el-table-column prop="name" label="姓名" width="180"></el-table-column>
    <el-table-column prop="address" label="地址"></el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄'
      }]
    }
  }
}
</script>

二、 <el-table> 详解 (根容器)

管理表格的整体行为和外观。

  • 关键属性:
    • data: 必填。绑定表格的数据源数组。
    • height / max-height: 设置表格的高度。设置 height 时,表格会固定高度,超出部分出现纵向滚动条。设置 max-height 时,表格高度随内容变化,但不超过最大值。
    • stripe: 是否显示斑马纹(隔行变色)。
    • border: 是否显示纵向边框。
    • fit: 列的宽度是否自撑开。true 时,列宽会根据内容自动调整(可能不精确)。
    • show-header: 是否显示表头。
    • highlight-current-row: 是否要高亮当前鼠标悬停的行。
    • current-row-key: 高亮某一行的 key,需要设置 row-key
    • row-key: 为数据行指定 key在使用 reserve-selection, expand, tree 等功能时非常重要 ,推荐始终设置。通常指向数据中唯一的字段(如 id)。
    • empty-text: 数据为空时显示的文本。
    • default-expand-all: 默认是否展开所有行(用于树形数据或展开行)。
    • tooltip-effect: hoverel-tooltip 的效果。dark / light
    • row-style: 行的 CSS 样式,可以是对象或返回对象的函数。
    • cell-style: 单元格的 CSS 样式,可以是对象或返回对象的函数。
    • header-row-style / header-cell-style: 表头行/单元格的样式。
    • row-class-name / cell-class-name: 为行/单元格添加自定义 class,可以是字符串或返回字符串的函数。
  • 关键事件:
    • @select: 当用户手动勾选数据行的 Checkbox 时触发。
    • @select-all: 当用户手动勾选全选 Checkbox 时触发。
    • @selection-change: 当选择项发生变化时触发。
    • @cell-mouse-enter / @cell-mouse-leave: 单元格 hover 事件。
    • @cell-click / @cell-dblclick: 单元格点击/双击事件。
    • @row-click / @row-dblclick: 行点击/双击事件。
    • @row-contextmenu: 行右键菜单事件。
    • @header-click / @header-contextmenu: 表头点击/右键菜单事件。
    • @sort-change: 当表格的排序条件发生变化时触发。
    • @filter-change: 当表格的筛选条件发生变化时触发。
    • @current-change: 当高亮行发生变化时触发。
    • @expand-change: 当行展开状态发生变化时触发。

三、 <el-table-column> 详解 (列定义)

定义表格的每一列,是表格功能的核心。

  • 关键属性:
    • type: 定义列的类型 。这是最重要的属性之一。
      • selection: 渲染一个 Checkbox,用于多选。通常放在第一列。
      • index: 渲染一个索引列,显示行的序号(从 1 开始)。
      • expand: 渲染一个可展开的按钮(+/-),用于展开行显示额外内容。
    • prop: 指定该列显示数据对象中的哪个属性 的值。例如 prop="name" 会显示 row.name
    • label: 该列的标题
    • width: 设置该列的宽度(像素值,如 180)。
    • min-width: 设置该列的最小宽度。当 fit=true 时,列宽会自适应,但不会小于 min-width
    • fixed: 列是否固定。true / left / right。固定列在表格横向滚动时会固定在左侧或右侧。
    • sortable: 该列是否可排序。true / customcustom 时需要监听 @sort-change 事件自行处理排序逻辑(常用于服务端排序)。
    • sort-method: 自定义排序方法的函数。
    • sort-by: 数组或字符串,指定排序时依据的属性或计算函数。
    • resizable: 对应列是否可以通过拖动改变宽度。true / false
    • column-key: 给列设置一个 key,用于 @filter-change 事件的回调参数。
    • align: 列内容的对齐方式。left / center / right
    • header-align: 表头的对齐方式。left / center / right。若不设置,则继承 align 的值。
    • show-overflow-tooltip: 当内容过长被隐藏时是否显示 tooltip。
    • formatter: 用来格式化显示文本的函数。function(row, column, cellValue, index)
    • filters: 数据过滤的选项。数组格式,如 [{ text: '2016-05-01', value: '2016-05-01' }]
    • filter-placement: 过滤弹出框的定位。top-start / top-end / bottom-start 等。
    • filter-multiple: 数据过滤的选项是否多选。
    • filter-method: 数据过滤使用的方法。function(value, row, column),返回 true 表示显示,false 表示隐藏。
    • filtered-value: 设置的筛选条件,需要配合 filter-method 使用。
  • 插槽 (Slots):
    • 默认插槽: 用于自定义列的内容。这是实现复杂列 (如操作按钮、状态标签、自定义组件)的最主要方式。插槽作用域 (slot-scope) 提供了 row (当前行数据), column (当前列对象), $index (行索引)。
    • header: 用于自定义表头的内容。

四、 常用功能详解

1. 多选 (Selection)
复制代码
<el-table
  :data="tableData"
  @selection-change="handleSelectionChange"
  ref="multipleTable"
>
  <!-- selection 列 -->
  <el-table-column type="selection" width="55"></el-table-column>
  <el-table-column prop="name" label="姓名"></el-table-column>
  <!-- ... -->
</el-table>

<script>
export default {
  methods: {
    handleSelectionChange(val) {
      this.multipleSelection = val; // val 是选中行的数据对象数组
    },
    toggleSelection(rows) {
      // 手动切换某行的选中状态
      if (rows) {
        rows.forEach(row => {
          this.$refs.multipleTable.toggleRowSelection(row);
        });
      } else {
        this.$refs.multipleTable.clearSelection();
      }
    }
  }
}
</script>
2. 排序 (Sorting)
复制代码
<!-- 简单前端排序 -->
<el-table-column prop="date" label="日期" sortable width="180"></el-table-column>

<!-- 自定义排序 (服务端排序) -->
<el-table-column
  prop="name"
  label="姓名"
  sortable="custom"
  @sort-change="handleSortChange"
></el-table-column>

<script>
export default {
  methods: {
    handleSortChange({ column, prop, order }) {
      // 根据 prop 和 order ('ascending', 'descending', null) 请求服务端数据
      console.log(`排序字段: ${prop}, 顺序: ${order}`);
      // fetchSortedData(prop, order);
    }
  }
}
</script>
3. 筛选 (Filtering)
复制代码
<el-table-column
  prop="tag"
  label="标签"
  :filters="[{ text: '家', value: '家' }, { text: '公司', value: '公司' }]"
  :filter-method="filterTag"
  filter-placement="bottom-end"
>
  <template slot-scope="scope">
    <!-- 使用 el-tag 展示标签 -->
    <el-tag :type="scope.row.tag === '家' ? 'primary' : 'success'" closeable>
      {{ scope.row.tag }}
    </el-tag>
  </template>
</el-table-column>

<script>
export default {
  methods: {
    filterTag(value, row) {
      return row.tag === value;
    }
  }
}
</script>
4. 自定义列内容 (使用插槽)

这是最强大的功能,可以实现几乎任何复杂的单元格内容。

复制代码
<el-table-column label="操作" width="180" fixed="right">
  <template slot-scope="scope">
    <el-button @click="handleEdit(scope.$index, scope.row)" size="mini">编辑</el-button>
    <el-button @click="handleDelete(scope.$index, scope.row)" size="mini" type="danger">删除</el-button>
    <!-- 条件渲染 -->
    <el-button v-if="scope.row.status === 0" size="mini" @click="handleEnable(scope.row)">启用</el-button>
    <el-button v-else size="mini" @click="handleDisable(scope.row)">禁用</el-button>
    <!-- 使用 switch -->
    <el-switch
      v-model="scope.row.enabled"
      active-color="#13ce66"
      inactive-color="#ff4949"
      @change="handleSwitchChange(scope.row)"
    >
    </el-switch>
  </template>
</el-table-column>
5. 展开行 (Expand)
复制代码
<el-table
  :data="tableData"
  style="width: 100%"
  :row-key="getRowKey" <!-- 重要:用于展开行 -->
>
  <!-- expand 列 -->
  <el-table-column type="expand" width="50">
    <template slot-scope="props">
      <p>详细信息: {{ props.row.detail }}</p>
      <p>描述: {{ props.row.description }}</p>
      <!-- 可以嵌套另一个表格 -->
      <!-- <el-table :data="props.row.subData">...</el-table> -->
    </template>
  </el-table-column>
  <el-table-column label="姓名" prop="name"></el-table-column>
  <!-- ... -->
</el-table>

<script>
export default {
  methods: {
    getRowKey(row) {
      return row.id; // 返回唯一标识
    }
  }
}
</script>
6. 树形数据与懒加载
复制代码
<el-table
  :data="tableData"
  style="width: 100%;margin-bottom: 20px;"
  row-key="id"
  border
  default-expand-all
  :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
  <el-table-column prop="name" label="名称" sortable></el-table-column>
  <el-table-column prop="date" label="日期" sortable></el-table-column>
  <el-table-column prop="address" label="地址"></el-table-column>
</el-table>

<!-- 懒加载 -->
<el-table
  :data="tableData"
  style="width: 100%"
  row-key="id"
  border
  :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  :load="load"
>
  <!-- ... -->
</el-table>

<script>
export default {
  methods: {
    load(tree, treeNode, resolve) {
      // 模拟异步加载
      setTimeout(() => {
        resolve([
          { id: 31, name: '叶子', date: '2016-05-01', address: '上海市' },
          { id: 32, name: '叶子2', date: '2016-05-01', address: '上海市' }
        ]);
      }, 1000);
    }
  }
}
</script>
7. 跨行/跨列合并 (Span Method)
复制代码
<el-table
  :data="tableData"
  :span-method="arraySpanMethod"
  border
  style="width: 100%"
>
  <!-- ... -->
</el-table>

<script>
export default {
  methods: {
    arraySpanMethod({ row, column, rowIndex, columnIndex }) {
      // 合并第一列(姓名)中相同值的行
      if (columnIndex === 0) {
        if (rowIndex % 2 === 0) {
          return {
            rowspan: 2, // 跨两行
            colspan: 1  // 跨一列
          };
        } else {
          return {
            rowspan: 0, // 不显示
            colspan: 0
          };
        }
      }
    }
  }
}
</script>

五、 高级技巧与最佳实践

  1. 性能优化:
    • row-key : 必须设置 ,尤其在数据量大或使用 reserve-selection, expand 时,能极大提升性能。
    • height / max-height: 设置固定高度,避免表格过长导致页面卡顿。
    • 虚拟滚动 : Element UI 原生不支持,但社区有第三方库(如 vue-virtual-scroll-list)可以集成实现超大数据量的流畅滚动。
  2. 分页集成: 通常 <el-table><el-pagination> 组件配合使用。<el-table> 显示当前页数据,<el-pagination> 控制页码,通过监听分页变化请求新数据。
  3. 自定义样式: 使用 row-style, cell-style, row-class-name, cell-class-name 或 CSS 覆盖(注意类名)来自定义表格样式。
  4. 空状态: 使用 empty-textslot="empty" 插槽自定义空数据时的展示内容(如图片、提示语)。
  5. 可访问性: 确保表头清晰,使用 aria-* 属性(如果框架支持)。
  6. 响应式: 表格在小屏幕上可能需要横向滚动。考虑使用 min-widthmax-width 控制列宽,或在移动端使用其他布局(如卡片列表)。

总结

Element UI 的 <el-table> 组件功能极其丰富,从基础的数据展示到复杂的多选、排序、筛选、展开、树形结构、合并单元格等,几乎涵盖了后台管理系统的所有表格需求。掌握 <el-table-column>type, prop, label, slot 以及 <el-table>data, row-key 是使用它的基础。灵活运用插槽 (slot-scope) 是实现复杂交互和自定义内容的关键。结合分页组件,可以构建出功能强大、用户体验良好的数据表格界面。

相关推荐
小蒜学长1 小时前
vue家教预约平台设计与实现(代码+数据库+LW)
java·数据库·vue.js·spring boot·后端
码海扬帆:前端探索之旅2 小时前
小程序开发指南(四)(UI 框架整合)
ui·微信小程序·小程序
chxii3 小时前
6.3Element UI 的表单
javascript·vue.js·elementui
张努力3 小时前
从零开始的开发一个vite插件:一个程序员的"意外"之旅 🚀
前端·vue.js
Adler_hu5 小时前
cli项目页面白屏时间优化
vue.js·webpack
Adler_hu5 小时前
高复用性组件封装指南
前端·vue.js
前端赵哈哈5 小时前
解决 Vue+TS 项目打包(vue-tsc -b && vite build)未使用变量提示 / 报错问题
前端·vue.js·vite
GHOME5 小时前
Vue2知识点详细回顾(以及自己的一些思考和解答)-3
前端·vue.js·面试
秋天的一阵风6 小时前
📝逐行拆解 event-source-polyfill 源码:理解 SSE polyfill 的设计思路
前端·vue.js·面试