承接上篇文章:vue3+el-table组件封装(理论部分)
1、publicTable组件
全部代码
<template>
<!-- 公用表格 -->
<div class="table-body">
<div class="body">
<div class="forms">
<el-table
ref="table"
:data="tableData"
:stripe="isStripe"
:border="showBorder"
row-key="Id"
:height="tableHeight2 ? tableHeight2 : tableHeight"
style="width: 100%"
v-loading="isLoading"
:highlight-current-row="showHighlight"
element-loading-text="数据加载中..."
:default-expand-all="false"
:header-row-class-name="tableRowClassName"
@expand-change="exChange"
@current-change="handleCurrentChange"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<!-- 是否有含有子内容的第一列 -->
<el-table-column type="selection" v-if="showSelection === true">
</el-table-column>
<el-table-column type="expand" v-if="showChild === true">
<slot name="expand-child"></slot>
</el-table-column>
<template v-for="(item, index) in tableHeaders" :key="index">
<!--不带插槽的列-->
<el-table-column
:prop="item.field"
:label="item.title"
v-if="item.slotName == ''"
:min-width="item.width"
label-class-name="tes0"
:show-overflow-tooltip="showTooltip"
/>
<!--带插槽的列 有固定列的列-->
<el-table-column
v-else-if="item.slotName == 'td_ID' || item.slotName == 'td_Id'"
:max-width="item.width > 0 ? item.width : 170"
fixed="right"
:prop="item.field"
:label="item.title"
label-class-name="tes0"
:show-overflow-tooltip="showTooltip"
>
<template #default="scope">
<slot :name="item.slotName" v-bind="scope"></slot>
</template>
</el-table-column>
<!--带插槽的列-->
<el-table-column
v-else
:prop="item.field"
:label="item.title"
:min-width="item.width"
label-class-name="tes0"
:show-overflow-tooltip="showTooltip"
>
<template #default="scope">
<slot :name="item.slotName" v-bind="scope"></slot>
</template>
</el-table-column>
</template>
</el-table>
</div>
<!-- 分页 -->
<div class="table-footer" v-if="showFooter">
<div class="footer-left">
{{ para.PageInfo.pageSize * (para.PageInfo.pageNum - 1) + 1 }}-{{
para.PageInfo.pageNum * para.PageInfo.pageSize > total
? total
: para.PageInfo.pageNum * para.PageInfo.pageSize
}}
/ {{ total }}
</div>
<el-pagination
:small="isSmall"
background
@current-change="handlePageChange"
layout="prev, pager, next, jumper"
:total="total"
:page-size="para.PageInfo.pageSize"
:pager-count="pagerCount"
>
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import { useSlots } from "vue";
export default {
props: {
tableHeight2: {
type: String,
},
pagerCount: {
type: Number,
default: 5,
},
isSmall: {
type: Boolean,
default: false,
},
isStripe: {
type: Boolean,
default: true,
},
showHighlight: {
type: Boolean,
default: false,
},
showTooltip: {
type: Boolean,
default: true,
},
showFooter: {
type: Boolean,
default: true,
},
showBorder: {
type: Boolean,
default: true,
},
showChild: {
type: Boolean,
default: false,
},
showSelection: {
type: Boolean,
default: false,
},
tableHeaders2: {
type: Array,
default: function () {
return [];
},
},
},
data() {
return {
slots: useSlots(), // 获取插槽信息
tableHeaders: [], //表头数据
tableData: [], //表格数据
isLoading: true, // 表格的loading效果
total: 0, // 总数
para: {
queryId: "",
PageInfo: { pageNum: 1, pageSize: 10 },
conditions: null,
},
tableHeight: "100%",
};
},
emits: ["expand-change", "changePage", "selectRow", "selectionChange"], //vue3子传父需写
methods: {
//开启loading
openLoadingStatus() {
this.isLoading = true
},
//选中复选框
handleSelectionChange(res) {
this.$emit("selectionChange", res);
},
setCurrent(row) {
this.$refs.table.setCurrentRow(row);
},
// 选中行
handleCurrentChange(val) {
this.$emit("selectRow", val);
},
//点击行
handleRowClick(val){
this.$emit('clickRow',val.value)
},
// 获取表格数据 父组件获取
getTData(para, res) {
this.para = para;
this.changeTableHeight();
this.tableData = res.rows;
this.total = res.total;
this.tableHeaders = this.tableHeaders2;
this.tableHeaders.forEach((col) => {
let _slotName = ''
if (col.title === '操作' && col.field === 'TDM') {
_slotName = "td_CAOZUO";
} else {
_slotName = "td_" + col.field;
}
if (typeof this.slots[_slotName] === "function") {
// 有插槽
col.slotName = _slotName;
} else {
// 没有插槽
col.slotName = "";
}
});
this.isLoading = false;
},
async exChange(row, rowList) {
this.$emit("expand-change", row, rowList);
},
// 分页
handlePageChange(val) {
if (this.tableHeaders2.length === 0) {
this.para.PageInfo.pageNum = val;
this.getDataList(this.para);
} else {
this.isLoading = true;
this.$emit("changePage", val);
}
},
//给表头加下划线
tableRowClassName({ rowIndex }) {
if (rowIndex === 0) {
return "header-row";
}
return "";
},
toggleRowExpansion(row) {
this.$refs.table.toggleRowExpansion(row);
},
},
};
</script>
<style>
.tes0 {
color: #000000;
}
.el-table__expanded-cell[class*="cell"] {
padding: 0px 50px;
}
.el-table .header-row th {
/* background: rgb(235, 161, 161)!important; */
border-bottom: 1px #ebe8e8 solid;
background: #f2f4f4;
}
.el-table .header-row th > .cell {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.el-table th,
.el-table td {
padding: 6px 0;
background: #ffffff;
}
</style>
<style scoped>
.body {
height: 100%;
display: flex;
justify-content: space-between;
flex-direction: column;
}
.tes {
color: #3c8dbc;
cursor: pointer;
}
.el-table tr {
color: #000000;
}
.table-footer {
display: flex;
align-items: center;
justify-content: space-between;
/* height: 50%; */
padding: 7px;
/* bottom:10%; */
overflow: hidden;
border-right: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
border-bottom: 1px solid #ebeef5;
background: #ffffff;
}
.footer-left {
float: left;
font-size: 13px;
color: var(--el-text-color-regular);
}
.el-pagination {
float: right;
}
.el-table .header-row th {
/* background: rgb(235, 161, 161)!important; */
border-bottom: 1px #ebe8e8 solid;
background: #f2f4f4 !important;
}
.el-table .header-row th > .cell {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
:deep(.el-table.danger-row) {
color: rgb(194, 15, 15);
}
.el-pagination :deep(.btn-prev .el-icon),
.el-pagination :deep(.btn-next .el-icon) {
display: inline-block;
}
</style>
2、组件引用
<template>
<PublicTable
ref="publicTable"
:tableHeaders2="tableHeaders2"
@changePage="handlePageChange"
>
<template #td_Id="scope">
<el-button size="mini" type="text" @click="editRows(scope.row)"
>修改</el-button
>
<el-button size="mini" type="text" @click="deleteData(scope.row)"
>删除</el-button
>
</template>
</PublicTable>
</template>
<script>
import PublicTable from '@/components/table/PublicTable.vue'
export default {
name: 'xx',
components: {
PublicTable
},
data() {
return {
tableHeaders2: [], //表头,
para: {
queryId: 'company_list',
PageInfo: { pageNum: 1, pageSize: 10 },
conditions: null,
},
}
},
methods: {
editRows(row) {
//编辑操作
},
deleteData(row) {
//删除操作
},
//获取表头数据
getLoadData() {
let me = this
this.$ajax
.get('url')
.then(function (response) {
if (response.data.isSuccess) {
me.tableHeaders2 = response.data.data
me.getDataList(me.para)
} else {
console.log(response.data.errorMessage)
}
})
},
//获取表格数据
async getDataList(para) {
this.para = para
let me = this
var res = await this.$ajax.post('url')
res = JSON.parse(res.data.data)
me.$refs.publicTable.getTData(me.para, res);//这里传递的res的值 上篇文章有说明;
},
// 分页
handlePageChange(val) {
this.para.PageInfo.pageNum = val
this.getDataList(this.para)
},
},
mounted() {
this.getLoadData();
},
}
</script>
3、总结
我这基本上可是把我现在使用的照搬过来了,可以好好参考下。 效果图: