🦄 refactor: 封装统一表格组件,便于批量扩展表格能力
This commit is contained in:
@@ -1,148 +1,132 @@
|
||||
<template>
|
||||
<div class="base-table">
|
||||
<!-- 给内部表格添加ref,方便暴露 -->
|
||||
<div class="my-table-container">
|
||||
<!-- 扩展层:可后续统一添加(如加载动画、导出按钮等) -->
|
||||
<div v-if="loading" class="table-loading">
|
||||
<el-loading-spinner></el-loading-spinner>
|
||||
<p class="loading-text">{{ loadingText || "加载中..." }}</p>
|
||||
</div>
|
||||
|
||||
<!-- 原生 Table 核心:透传 props/事件/插槽 -->
|
||||
<el-table
|
||||
ref="internalTable"
|
||||
:ref="tableRef"
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners"
|
||||
:data="data"
|
||||
:loading="loading"
|
||||
:class="['my-table', customClass]"
|
||||
>
|
||||
<!-- 通过配置数组渲染列 -->
|
||||
<template v-for="(column, index) in columns">
|
||||
<el-table-column
|
||||
v-if="column.visible !== false"
|
||||
v-bind="column"
|
||||
>
|
||||
<!-- 列的自定义内容插槽 -->
|
||||
<template v-if="column.slot" #default="scope">
|
||||
<slot :name="column.slot" :scope="scope"></slot>
|
||||
</template>
|
||||
|
||||
<!-- 表头自定义内容 -->
|
||||
<template v-if="column.headerSlot" #header>
|
||||
<slot :name="column.headerSlot"></slot>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column
|
||||
v-if="showActionColumn"
|
||||
:label="actionColumnLabel"
|
||||
:width="actionColumnWidth"
|
||||
:fixed="actionColumnFixed"
|
||||
:align="actionColumnAlign"
|
||||
<!-- 1. 透传“列定义插槽”(原生 columns 中通过 slot 自定义的表头/单元格) -->
|
||||
<template
|
||||
v-for="(column, index) in $attrs.columns || []"
|
||||
v-slot:[`header-${column.prop}`]="scope"
|
||||
>
|
||||
<template #default="scope">
|
||||
<slot name="action" :scope="scope"></slot>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 原生插槽,支持直接写el-table-column -->
|
||||
<slot></slot>
|
||||
<!-- 调用业务层定义的表头插槽 -->
|
||||
<slot :name="`header-${column.prop}`" v-bind="scope"></slot>
|
||||
</template>
|
||||
<template
|
||||
v-for="(column, index) in $attrs.columns || []"
|
||||
v-slot:[column.prop]="scope"
|
||||
>
|
||||
<!-- 调用业务层定义的单元格插槽 -->
|
||||
<slot :name="column.prop" v-bind="scope"></slot>
|
||||
</template>
|
||||
|
||||
<!-- 2. 透传原生内置插槽(如 empty 空数据插槽、append 底部插槽等) -->
|
||||
<template v-slot:empty="scope">
|
||||
<slot name="empty" v-bind="scope"></slot>
|
||||
</template>
|
||||
<template v-slot:append="scope">
|
||||
<slot name="append" v-bind="scope"></slot>
|
||||
</template>
|
||||
|
||||
<!-- 3. 透传“自定义列”插槽(业务层直接用 <el-table-column> 嵌套的情况) -->
|
||||
<slot v-bind:tableRef="tableRef"></slot>
|
||||
</el-table>
|
||||
|
||||
<!-- 扩展层:可后续统一添加分页(如与 MyPagination 组件联动) -->
|
||||
<slot name="pagination"></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BaseTable',
|
||||
name: "KLPTable", // 组件名,便于调试和文档生成
|
||||
props: {
|
||||
// 表格数据
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 列配置数组
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 是否显示加载状态
|
||||
// 1. 扩展 props:新增原生 Table 没有的属性(如加载状态)
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示操作列
|
||||
showActionColumn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 操作列标题
|
||||
actionColumnLabel: {
|
||||
loadingText: {
|
||||
type: String,
|
||||
default: '操作'
|
||||
default: "加载中..."
|
||||
},
|
||||
// 操作列宽度
|
||||
actionColumnWidth: {
|
||||
type: Number,
|
||||
default: 150
|
||||
},
|
||||
// 操作列固定方式
|
||||
actionColumnFixed: {
|
||||
// 2. 兼容原生 class 用法(原生 el-table 支持 class 属性,此处显式接收避免 $attrs 冲突)
|
||||
customClass: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
// 操作列内容对齐方式
|
||||
actionColumnAlign: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
// 暴露内部表格的方法和属性
|
||||
data() {
|
||||
return {
|
||||
tableRef: "myTableRef" // 表格 ref,便于后续通过 ref 调用原生方法
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 获取内部el-table实例
|
||||
*/
|
||||
// 3. 透传原生 Table 实例方法(如 clearSelection、doLayout 等)
|
||||
// 业务层可通过 this.$refs.myTable.xxx() 调用原生方法
|
||||
getTableInstance() {
|
||||
return this.$refs.internalTable
|
||||
return this.$refs[this.tableRef];
|
||||
},
|
||||
|
||||
/**
|
||||
* 代理el-table的常用方法,方便直接调用
|
||||
*/
|
||||
// 示例:透传原生 clearSelection 方法
|
||||
clearSelection() {
|
||||
if (this.$refs.internalTable) {
|
||||
this.$refs.internalTable.clearSelection()
|
||||
const table = this.getTableInstance();
|
||||
if (table && table.clearSelection) {
|
||||
table.clearSelection();
|
||||
}
|
||||
},
|
||||
|
||||
// 可根据需要扩展更多原生方法(如 toggleRowSelection、sort 等)
|
||||
toggleRowSelection(row, selected) {
|
||||
if (this.$refs.internalTable) {
|
||||
this.$refs.internalTable.toggleRowSelection(row, selected)
|
||||
}
|
||||
},
|
||||
|
||||
toggleAllSelection() {
|
||||
if (this.$refs.internalTable) {
|
||||
this.$refs.internalTable.toggleAllSelection()
|
||||
}
|
||||
},
|
||||
|
||||
doLayout() {
|
||||
if (this.$refs.internalTable) {
|
||||
this.$refs.internalTable.doLayout()
|
||||
}
|
||||
},
|
||||
|
||||
sort(prop, order) {
|
||||
if (this.$refs.internalTable) {
|
||||
this.$refs.internalTable.sort(prop, order)
|
||||
const table = this.getTableInstance();
|
||||
if (table && table.toggleRowSelection) {
|
||||
table.toggleRowSelection(row, selected);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 提供一个$refs的代理,方便访问内部表格
|
||||
mounted() {
|
||||
// 可以在这里添加一些初始化逻辑
|
||||
// 扩展点:后续可统一添加初始化逻辑(如权限控制、默认排序等)
|
||||
console.log("MyTable 初始化完成,原生实例:", this.getTableInstance());
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.base-table {
|
||||
.my-table-container {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
/* 扩展样式:加载状态遮罩(后续可统一调整) */
|
||||
.table-loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 12px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 原生 Table 样式兼容:避免封装层影响原生样式 */
|
||||
.my-table {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user