一、 核心组成与基本结构
Element UI 的表格主要由以下几个核心部分构成:
<el-table>: 表格的根容器,负责管理数据、选择、排序、分页集成等全局状态。<el-table-column>: 定义表格的一列。表格的列结构由一个或多个<el-table-column>组件定义。data: 传递给<el-table>的data属性,是一个数组,数组中的每个对象代表表格中的一行数据。prop:<el-table-column>的prop属性,指定该列显示data数组中每个对象的哪个属性的值。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:hover时el-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/custom。custom时需要监听@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>
五、 高级技巧与最佳实践
- 性能优化:
row-key: 必须设置 ,尤其在数据量大或使用reserve-selection,expand时,能极大提升性能。height/max-height: 设置固定高度,避免表格过长导致页面卡顿。- 虚拟滚动 : Element UI 原生不支持,但社区有第三方库(如
vue-virtual-scroll-list)可以集成实现超大数据量的流畅滚动。
- 分页集成: 通常
<el-table>与<el-pagination>组件配合使用。<el-table>显示当前页数据,<el-pagination>控制页码,通过监听分页变化请求新数据。 - 自定义样式: 使用
row-style,cell-style,row-class-name,cell-class-name或 CSS 覆盖(注意类名)来自定义表格样式。 - 空状态: 使用
empty-text或slot="empty"插槽自定义空数据时的展示内容(如图片、提示语)。 - 可访问性: 确保表头清晰,使用
aria-*属性(如果框架支持)。 - 响应式: 表格在小屏幕上可能需要横向滚动。考虑使用
min-width和max-width控制列宽,或在移动端使用其他布局(如卡片列表)。
总结
Element UI 的 <el-table> 组件功能极其丰富,从基础的数据展示到复杂的多选、排序、筛选、展开、树形结构、合并单元格等,几乎涵盖了后台管理系统的所有表格需求。掌握 <el-table-column> 的 type, prop, label, slot 以及 <el-table> 的 data, row-key 是使用它的基础。灵活运用插槽 (slot-scope) 是实现复杂交互和自定义内容的关键。结合分页组件,可以构建出功能强大、用户体验良好的数据表格界面。