基于Vue3和Element Plus實現可擴展的表格組件
引言
在開發(fā)過程中,我們經常需要創(chuàng)建具有復雜功能的表格組件。本文將介紹如何使用 Vue 3 和 Element Plus 庫來構建一個可擴展的表格組件,包括增加自定義插槽、操作欄按鈕以及動態(tài)列內容。
組件概述
我們將創(chuàng)建一個名為 Table 的 Vue 組件,該組件具有以下特性:
- 支持固定表頭和邊框
- 可配置的列寬和最小列寬
- 支持樹形數據和展開行
- 自定義列內容和操作欄按鈕
- 動態(tài)計算表格高度
以下是組件的實現步驟和代碼示例。
組件實現
1. 組件模板
首先,我們定義組件的模板部分,使用 el-table 組件來創(chuàng)建表格,并添加三個自定義插槽:default、operationsStart 和 operationsEnd。
<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>
2. 組件腳本
在腳本部分,我們定義了組件的 props、slots 和 emits,以及一些必要的響應式數據和函數。
<script setup lang="ts">
// 使用 unknown 類型表示任何值
type MyUnknownType = unknown;
/*
* @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?: unknown;
// 加載狀態(tài)
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: [],
tableModels: () => [],
treeProps: () => [],
shoeOperations: true,
operationsWidth: 150,
operationsAlign: 'center',
operationsHeaderAlign: 'center',
expandRowKeys: [],
minWidth: 'auto',
height: 'auto'
});
// 插槽對象
const slots = useSlots();
// 定義組件發(fā)出的事件
const emit = defineEmits(['handleEdit', 'handleDelete', 'handlePagination', 'handleSelectionChange', 'handlePage']);
const tableHeight = ref<any>();
// watch監(jiān)聽動態(tài)計算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>
3. 使用案例
以下是如何在父組件中使用 Table 組件的示例,包括自定義列內容和操作欄按鈕。
<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>
4. 渲染表格的數據
最后,我們定義表格的列模型和數據。
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: "狀態(tài)",
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,
});
結論
通過以上步驟,我們創(chuàng)建了一個功能豐富、可擴展的表格組件。這個組件可以根據實際需求調整列配置、操作按鈕和自定義內容,非常適合在復雜的應用場景中使用。
以上就是基于Vue3和Element Plus實現可擴展的表格組件的詳細內容,更多關于Vue3 Element Plus表格組件的資料請關注腳本之家其它相關文章!
相關文章
Element-UI表格嵌入popover遇到的問題及解決方案
在表格中我們通常需要在每一行的一些單元格中顯示popover,這篇文章主要給大家介紹了關于Element-UI表格嵌入popover遇到的問題及解決方案,需要的朋友可以參考下2023-11-11
解決vite.config.js無法使用__dirname的問題
這篇文章主要介紹了解決vite.config.js無法使用__dirname的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10

