Vue3 + Element Plus 实现表格全选/反选/禁用功能详解
一、功能概述与最终效果
本文将基于Vue3组合式API,实现Element Plus表格的以下核心功能:
- 全选/全不选:表头复选框控制全部数据
- 反选功能:快速反转当前选中状态
- 行禁用:禁止选中特定数据行
- 分页保持:分页切换时保留选中状态
二、基础表格搭建
<template>
<div class="table-demo">
<el-table
ref="tableRef"
:data="tableData"
row-key="id"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" :selectable="checkSelectable" />
<el-table-column prop="name" label="姓名" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="status" label="状态" />
</el-table>
<div class="operate-btns">
<el-button @click="toggleAll">全选/反选</el-button>
<el-button @click="reverseSelect">反选</el-button>
</div>
</div>
</template>
三、核心功能实现
1. 数据准备与禁用控制
import { ref } from 'vue'
interface TableItem {
id: number
name: string
age: number
status: '正常' | '禁用'
}
// 响应式数据
const tableRef = ref()
const tableData = ref<TableItem[]>([
{ id: 1, name: '张三', age: 25, status: '正常' },
{ id: 2, name: '李四', age: 30, status: '禁用' },
// 更多数据...
])
// 禁用判断方法
const checkSelectable = (row: TableItem) => {
return row.status !== '禁用'
}
2. 全选/全不选实现
const toggleAll = () => {
// 获取当前页所有可选项
const selectableRows = tableData.value.filter(row => checkSelectable(row))
// 判断是否需要全选
const shouldSelectAll = selectableRows.some(row =>
!tableRef.value?.getRowSelected(row)
)
tableData.value.forEach(row => {
if (checkSelectable(row)) {
tableRef.value?.toggleRowSelection(row, shouldSelectAll)
}
})
}
3. 反选功能实现
const reverseSelect = () => {
const currentSelection = tableRef.value?.getSelectionRows() || []
const selectableRows = tableData.value.filter(row => checkSelectable(row))
selectableRows.forEach(row => {
const isSelected = currentSelection.some(
(selected: TableItem) => selected.id === row.id
)
tableRef.value?.toggleRowSelection(row, !isSelected)
})
}
4. 选中状态保持(配合分页)
// 存储选中ID
const selectedIds = ref<number[]>([])
// 监听选中变化
const handleSelectionChange = (rows: TableItem[]) => {
selectedIds.value = rows.map(row => row.id)
}
// 分页切换时恢复选中
const handlePageChange = () => {
nextTick(() => {
tableData.value.forEach(row => {
if (selectedIds.value.includes(row.id)) {
tableRef.value?.toggleRowSelection(row, true)
}
})
})
}
四、功能增强技巧
1. 表头复选框样式优化
::v-deep .el-table__header-wrapper .el-checkbox {
display: inline-flex;
&__inner::after {
border-color: #fff;
}
&.is-disabled {
opacity: 0.6;
cursor: not-allowed;
}
}
2. 禁用行视觉提示
<el-table :row-class-name="setDisabledStyle">
<script>
const setDisabledStyle = ({ row }: { row: TableItem }) => {
return row.status === '禁用' ? 'disabled-row' : ''
}
</script>
<style>
.disabled-row {
opacity: 0.6;
cursor: not-allowed;
td:first-child .el-checkbox {
display: none;
}
}
</style>
五、完整组件代码
<template>
<div class="table-container">
<el-table
ref="tableRef"
:data="tableData"
:row-class-name="setDisabledStyle"
row-key="id"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
:selectable="checkSelectable"
/>
<el-table-column prop="name" label="姓名" />
<el-table-column prop="age" label="年龄" />
<el-table-column prop="status" label="状态" />
</el-table>
<div class="table-actions">
<el-button type="primary" @click="toggleAll">
{{ isAllSelected ? '取消全选' : '全选' }}
</el-button>
<el-button @click="reverseSelect">反选</el-button>
<span class="selected-count">已选:{{ selectedIds.length }} 项</span>
</div>
<el-pagination
layout="prev, pager, next"
:total="50"
@current-change="handlePageChange"
/>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, computed } from 'vue'
// 数据与状态定义...
// 此处插入前面章节的实现代码
</script>
<style scoped>
/* 样式优化代码... */
</style>
六、常见问题解决方案
Q1: 分页切换后选中状态丢失?
- 方案:使用row-key绑定唯一标识,配合selection-change存储选中ID
Q2: 禁用行仍可被全选选中?
- 检查点:
- selectable方法是否正确返回布尔值
- 全选逻辑是否过滤了不可选数据
Q3: 大数据量性能问题?
- 优化建议:
- 使用虚拟滚动(el-table-v2)
- 避免在模板中使用复杂表达式
- 使用Web Worker处理数据筛选
七、扩展思考
- 服务端分页场景:需要结合接口传递选中ID集合
- 树形表格处理:使用el-table的tree-props配置
- 多级表头支持:嵌套el-table-column实现复杂表头
- 无障碍访问:为操作按钮添加ARIA标签
通过合理运用Element Plus提供的API和Vue3响应式特性,可以构建出功能强大且用户体验良好的表格组件。建议在实际开发中根据具体业务需求灵活调整实现方案。