基于Vue3和Element Plus實現(xiàn)可擴展的表格組件
引言
在開發(fā)過程中,我們經(jīng)常需要創(chuàng)建具有復(fù)雜功能的表格組件。本文將介紹如何使用 Vue 3 和 Element Plus 庫來構(gòu)建一個可擴展的表格組件,包括增加自定義插槽、操作欄按鈕以及動態(tài)列內(nèi)容。
組件概述
我們將創(chuàng)建一個名為 Table
的 Vue 組件,該組件具有以下特性:
- 支持固定表頭和邊框
- 可配置的列寬和最小列寬
- 支持樹形數(shù)據(jù)和展開行
- 自定義列內(nèi)容和操作欄按鈕
- 動態(tài)計算表格高度
以下是組件的實現(xiàn)步驟和代碼示例。
組件實現(xiàn)
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,以及一些必要的響應(yīng)式數(shù)據(jù)和函數(shù)。
<script setup lang="ts"> // 使用 unknown 類型表示任何值 type MyUnknownType = unknown; /* * @slot default 插槽 * operationsStart 從操作欄開頭增加按鈕 * operationsStart 從操作欄結(jié)尾增加按鈕 * Key TableModel里面的Key,用來自定義列的內(nèi)容 * */ import { Delete, Edit } from '@element-plus/icons-vue'; // 【接口】table表格模型 interface ITableModel { // 表頭顯示文字 label: string; // 表格列Keu key: string; // 表格列寬 width?: number | string; // 表格列顯示文字 value?: string; // 表格內(nèi)容位置 align?: string; // 表格表頭位置 headerAlign?: string; // 列最小寬度 minWidth?: number | string; } // 【接口】接受傳參字段 interface IProps { // 生成表格參數(shù) tableModels?: ITableModel[]; // 表格數(shù)據(jù) data: object[]; // 是否為樹形表格 treeProps?: unknown; // 加載狀態(tài) loading?: boolean; // 表格行Keu rowKey?: any; // 表格高度 height?: any; // 表格自適應(yīng)減去的高度 // eslint-disable-next-line vue/prop-name-casing dynamic?: number; // 表格單選 highlightCurrentRow?: boolean; // 是否顯示編輯按鈕 showEditBtn?: boolean; // 是否顯示多選框 showSelection?: boolean; // 是否顯示刪除按鈕 showDeleteBtn?: boolean; // 刪除權(quán)限 deleteHasPerm?: any; // 編輯權(quán)限 editHasPerm?: any; // 操作欄寬度 operationsWidth?: number; // 是否顯示操作欄 shoeOperations?: boolean; // 操作欄內(nèi)容位置 operationsAlign?: string; // 操作欄頭部位置 operationsHeaderAlign?: string; // 操作欄最小寬度 minWidth?: number | string; // 樹表格時默認展開參數(shù) expandRowKeys?: any; } // 【接口】分頁 interface IPage { // 當(dāng)前頁 pageNum: number; // 每頁顯示條數(shù) pageSize: number; } // 初始化默認參數(shù) 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的高度,根據(jù)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
組件的示例,包括自定義列內(nèi)容和操作欄按鈕。
<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)" > 分配權(quán)限 </el-button> </template> </Table>
4. 渲染表格的數(shù)據(jù)
最后,我們定義表格的列模型和數(shù)據(jù)。
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: "數(shù)據(jù)權(quán)限", 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, });
結(jié)論
通過以上步驟,我們創(chuàng)建了一個功能豐富、可擴展的表格組件。這個組件可以根據(jù)實際需求調(diào)整列配置、操作按鈕和自定義內(nèi)容,非常適合在復(fù)雜的應(yīng)用場景中使用。
以上就是基于Vue3和Element Plus實現(xiàn)可擴展的表格組件的詳細內(nèi)容,更多關(guān)于Vue3 Element Plus表格組件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue實戰(zhàn)之vue登錄驗證的實現(xiàn)代碼
本篇文章主要介紹了Vue實戰(zhàn)之vue登錄的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10Element-UI表格嵌入popover遇到的問題及解決方案
在表格中我們通常需要在每一行的一些單元格中顯示popover,這篇文章主要給大家介紹了關(guān)于Element-UI表格嵌入popover遇到的問題及解決方案,需要的朋友可以參考下2023-11-11詳解利用eventemitter2實現(xiàn)Vue組件通信
這篇文章主要介紹了詳解利用eventemitter2實現(xiàn)Vue組件通信,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11解決vite.config.js無法使用__dirname的問題
這篇文章主要介紹了解決vite.config.js無法使用__dirname的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10