代码中主要增加了3个插槽,operationsStart 从操作栏开头增加按钮,operationsStart 从操作栏结尾增加按钮,还有一个插槽用来自定义列的内容,就是 TableModel里面的Key
javascript
<template>
<el-table
border
stripe
:data="data"
:height="tableHeight"
table-layout="fixed"
:row-key="rowKey"
:highlight-current-row="highlightCurrentRow"
:tree-props="treeProps"
:header-cell-style="{
background: '#f5f7fa',
color: '#606266',
fontSize: '13px',
}"
@selection-change="handleSelectionChange"
:v-loading="loading"
:row-class-name="tableRowClassName"
:expand-row-keys="expandRowKeys"
class="absolute"
>
<el-table-column
v-if="showSelection"
align="center"
fixed
type="selection"
width="55"
/>
<el-table-column
v-for="tableModel in tableModels"
:key="tableModel.key"
:prop="tableModel.key"
:label="tableModel.label"
:width="tableModel.width"
:min-width="tableModel.minWidth"
:align="tableModel.align"
:header-align="tableModel.headerAlign"
>
<template #default="{ row }">
<slot
v-if="slots[tableModel.key]"
:name="tableModel.key"
v-bind="row"
></slot>
<span v-else>
{{ row[tableModel.key] }}
</span>
</template>
</el-table-column>
<el-table-column
fixed="right"
label="操作"
:width="operationsWidth"
:min-width="minWidth"
:align="operationsAlign"
:header-align="operationsHeaderAlign"
v-if="shoeOperations"
>
<template #default="{ row, $index }">
<slot name="operationsStart" v-bind="row"></slot>
<el-button
link
type="primary"
:icon="Edit"
@click="handleEdit(row, $index)"
:v-hasPerm="editHasPerm"
v-if="showEditBtn"
>编辑
</el-button>
<el-button
@click="handleDelete(row, $index)"
link
type="danger"
:icon="Delete"
v-if="showDeleteBtn"
:v-hasPerm="deleteHasPerm"
>删除
</el-button>
<slot name="operationsEnd" v-bind="row"></slot>
</template>
</el-table-column>
</el-table>
</template>
javascript
<script setup lang="ts">
/*
* @slot default 插槽
* operationsStart 从操作栏开头增加按钮
* operationsStart 从操作栏结尾增加按钮
* Key TableModel里面的Key,用来自定义列的内容
* */
import { Delete, Edit } from "@element-plus/icons-vue";
// 【接口】table表格模型
interface ITableModel {
// 表头显示文字
label: string;
// 表格列Keu
key: string;
// 表格列宽
width?: number | string;
// 表格列显示文字
value?: string;
// 表格内容位置
align?: string;
// 表格表头位置
headerAlign?: string;
// 列最小宽度
minWidth?: number | string;
}
// 【接口】接受传参字段
interface IProps {
// 生成表格参数
tableModels?: ITableModel[];
// 表格数据
data: object[];
// 是否为树形表格
treeProps?: Object;
// 加载状态
loading?: boolean;
// 表格行Keu
rowKey?: any;
// 表格高度
height?: any;
// 表格自适应减去的高度
// eslint-disable-next-line vue/prop-name-casing
dynamic?: number;
// 表格单选
highlightCurrentRow?: boolean;
// 是否显示编辑按钮
showEditBtn?: boolean;
// 是否显示多选框
showSelection?: boolean;
// 是否显示删除按钮
showDeleteBtn?: boolean;
// 删除权限
deleteHasPerm?: any;
// 编辑权限
editHasPerm?: any;
// 操作栏宽度
operationsWidth?: number;
// 是否显示操作栏
shoeOperations?: boolean;
// 操作栏内容位置
operationsAlign?: string;
// 操作栏头部位置
operationsHeaderAlign?: string;
// 操作栏最小宽度
minWidth?: number | string;
// 树表格时默认展开参数
expandRowKeys?: any;
}
// 【接口】分页
interface IPage {
// 当前页
pageNum: number;
// 每页显示条数
pageSize: number;
}
// 初始化默认参数
const props = withDefaults(defineProps<IProps>(), {
loading: false,
rowKey: "id",
dynamic: 0,
showEditBtn: true,
highlightCurrentRow: false,
showSelection: false,
showDeleteBtn: true,
deleteHasPerm: [],
editHasPerm: [],
shoeOperations: true,
operationsWidth: 150,
operationsAlign: "center",
operationsHeaderAlign: "center",
expandRowKeys: [],
});
// 插槽对象
const slots = useSlots();
// 定义组件发出的事件
const emit = defineEmits([
"handleEdit",
"handleDelete",
"handlePagination",
"handleSelectionChange",
"handlePage",
]);
const tableHeight = ref<any>();
// watch监听动态计算table的高度,根据dynamic是否大于0,dynamic层级大于height
watch(
[() => props.height, () => props.dynamic],
([height, dynamic]) => {
if (height && !dynamic) {
tableHeight.value = height;
} else if ((!height && dynamic) || (height && dynamic)) {
// 获取浏览器窗口高度
const windowHeight = window.innerHeight;
tableHeight.value = windowHeight - dynamic;
} else {
tableHeight.value = "auto";
}
},
{
deep: true,
immediate: true,
}
);
// 增加样式Class
const tableRowClassName = ({
row,
rowIndex,
}: {
row: Object;
rowIndex: number;
}) => {
if (rowIndex % 2 === 1) {
return "warning-row";
}
return "";
};
// 点了多选
const handleSelectionChange = (val: ITableModel[]) => {
emit("handleSelectionChange", val);
};
// 点击了编辑
const handleEdit = (data: object, index: number) => {
emit("handleEdit", data, index);
};
// 点击了删除
const handleDelete = (data: object, index: number) => {
emit("handleDelete", data, index);
};
</script>
使用案例
javascript
<Table
:dynamic="dynamicHeight"
:tableModels="table.tableModels"
:data="table.data"
:loading="table.loading"
:showSelection="table.showSelection"
:operationsWidth="table.operationsWidth"
@handle-edit="openDialog"
@handle-delete="handleDelete"
@handle-selection-change="handleSelectionChange"
>
<!-- 自定义列【status】字段 -->
<template #status="scope">
<el-tag size="small" v-if="scope.status === 1" type="success">
正常
</el-tag>
<el-tag size="small" v-else type="info">禁用</el-tag>
</template>
<!-- 操作栏从开头增加按钮 -->
<template #operationsStart="scope">
<el-button
type="primary"
size="small"
link
:icon="Position"
@click="openMenuDialog(scope)"
>
分配权限
</el-button>
</template>
</Table>
渲染表格的数据
javascript
const table = reactive({
tableModels: [
{
label: "角色名称",
key: "name",
align: "left",
headerAlign: "center",
value: "name",
minWidth: 200,
},
{
label: "角色编码",
key: "code",
width: 200,
align: "center",
headerAlign: "center",
value: "code",
},
{
label: "数据权限",
key: "dataScope",
width: 200,
align: "center",
headerAlign: "center",
value: "dataScope",
},
{
label: "状态",
key: "status",
width: 200,
align: "center",
headerAlign: "center",
value: "status",
},
{
label: "排序",
key: "sort",
width: 200,
align: "center",
headerAlign: "center",
value: "sort",
},
],
data: [] as any[],
showSelection: true,
operationsWidth: 250,
loading: false,
});