因日常工作会大量使用table表格,今天就封装一个简易版本, 话不多说上代码!
<script setup>
import { reactive, watch } from "vue";
const props = defineProps({
staticStatePaging: {
type: Boolean,
default: false,
},
// 表格配置
tableConfig: {
type: Object,
required: true,
default() {
return {
stripe: true,
pageSizeArr: [10, 20, 50, 100],
border: false, // 是否带有纵向边框,默认为false
hasSelect: false, // 有无选中功能
hasOperation: false, // 有无操作功能
hasExpand: false, // 有无展开行功能
rowClick: false, // 是否开启行点击
columns: [],
operation: {},
expands: [],
searchProp: {},
pagination: {},
formatTableData: (res) => res,
};
},
},
// 请求配置 返回一个·promise
requestFun: {
type: Function,
},
tableDataProp: {
type: Array,
default: () => {
return [];
},
},
tableDataPropTotal: {
type: Number,
default: 0,
},
// 动态配置项(查询参数)
requestData: {
type: Object,
default() {
return {
requestParamsOrData: {
current: 1,
pageSize: 10,
},
};
},
},
// 初始不发请求(适用于页面初始加载业务组件传参查询的情况)
initPersonTable: {
type: Boolean,
default: false,
},
});
const tableMsg = reactive({
data: [],
totalCount: 0,
loading: false,
});
// 事件注册
const emit = defineEmits([
"onHandleSizeChange",
"onHandleCurrentChange",
"update:requestParamsOrData",
"onOperateBtn",
]);
watch(
() => props.tableDataProp,
(newV) => {
if (props.staticStatePaging) {
if (newV?.length > props.requestData.requestParamsOrData.pageSize) {
tableMsg.data = newV.slice(
0,
props.requestData.requestParamsOrData.pageSize
);
emit("update:requestParamsOrData", {
...props.requestData.requestParamsOrData,
current: 1,
});
} else {
tableMsg.data = newV;
}
tableMsg.totalCount = newV.length;
} else {
tableMsg.data = newV;
tableMsg.totalCount = props.tableDataPropTotal;
}
},
{ deep: true, immediate: true }
);
watch(
() => props.requestData,
() => {
if (props.requestFun) {
getData();
}
},
{
deep: true,
}
);
const getData = async () => {
tableMsg.loading = true;
const config = formatSearch();
const formatData = props.tableConfig.formatTableData;
if (props.requestFun) {
await props.requestFun(config.data, config.params).then(
async (res) => {
tableMsg.loading = false;
tableMsg.data = formatData(res).data;
tableMsg.totalCount = formatData(res).totalCount;
},
() => {
tableMsg.data = [];
tableMsg.totalCount = 0;
tableMsg.loading = false;
}
);
} else {
tableMsg.loading = false;
}
};
// 格式化请求参数
const formatSearch = () => {
let params = {};
let data = {};
for (const k in props.requestData.requestParamsOrData) {
if (
props.tableConfig?.searchProp?.[k] &&
props.tableConfig?.searchProp?.[k] === "params"
) {
params = {
...params,
[k]: props.requestData.requestParamsOrData[k],
};
} else {
data = {
...data,
[k]: props.requestData.requestParamsOrData[k],
};
}
}
const finalObj =
JSON.stringify(params) === "{}" ? { data } : { params, data };
return finalObj;
};
const handleSizeChange = (val) => {
if (props.staticStatePaging) {
emit("update:requestParamsOrData", {
...props.requestData.requestParamsOrData,
pageSize: val,
});
let num = val;
let currentPage = props.requestData.requestParamsOrData.current;
let totalNum = (currentPage - 1) * num;
tableMsg.data = props.tableDataProp.slice(totalNum, num + totalNum) || [];
} else {
emit("onHandleSizeChange", val);
}
};
const handleCurrentChange = (val) => {
if (props.staticStatePaging) {
emit("update:requestParamsOrData", {
...props.requestData.requestParamsOrData,
current: val,
});
let num = props.requestData.requestParamsOrData.pageSize;
let currentPage = val;
let totalNum = (currentPage - 1) * num;
tableMsg.data = props.tableDataProp.slice(totalNum, num + totalNum) || [];
} else {
emit("onHandleCurrentChange", val);
}
};
const handleOperation = (item, row) => {
emit("onOperateBtn", {
item,
row,
});
};
getData();
</script>
<template>
<div>
<el-table
:data="tableMsg.data"
:key="tableConfig.key || 'myTable'"
v-loading="tableMsg.loading"
:tableConfig="tableConfig"
:max-height="tableConfig.height || '650'"
:height="tableConfig.minHeight"
style="width: 100%"
:header-cell-style="{
background: '#f0f1f5',
color: '#000000',
}"
>
<el-table-column
v-for="item in tableConfig.columns"
:key="item.id"
:label="item.label"
:prop="item.prop"
:class-name="item.className ? item.className : ''"
:width="item.width ? item.width : ''"
:sortable="item.sortable"
:min-width="item.minWidth ? item.minWidth : ''"
:show-overflow-tooltip="!item.hideTooltip"
:fixed="item.fixed"
:align="item.align"
>
<template v-slot="scope">
<!-- 自定义模板 使用slot -->
<template
v-if="item.show === 'template' || item.showType === 'template'"
>
<slot :name="item.prop" :scope="scope" />
</template>
<!-- 正常渲染数据列 -->
<template v-else-if="item.show === 'function'">
{{ item.valueFun(scope.row[item.prop], scope.row) }}
</template>
<template v-else-if="item.show !== 'template'">
{{
item.formatData
? item.formatData(scope.row[item.prop])
: scope.row[item.prop]
}}
</template>
</template>
</el-table-column>
<!-- 操作列 -->
<el-table-column
v-if="tableConfig.hasOperation"
column-key="operation"
:label="tableConfig.operation.label"
:width="tableConfig.operation.width ? tableConfig.operation.width : ''"
:min-width="
tableConfig.operation.minWidth ? tableConfig.operation.minWidth : ''
"
:class-name="tableConfig.operation.className"
:fixed="tableConfig.operation.fixed"
>
<template v-slot="scope">
<slot name="operation" :scope="scope">
<el-button
v-for="item in tableConfig.operation.data"
:key="item.id"
:class="item.className ? item.className : ''"
:size="item.size || 'small'"
:type="item.type || 'info'"
:link="item.link || true"
:text="item.text || true"
@click.stop="handleOperation(item, scope.row)"
>
{{ item.label }}
</el-button>
</slot>
</template>
</el-table-column>
</el-table>
<div class="clearfix">
<el-pagination
v-if="tableConfig.pagination && !tableConfig.pagination.hidden"
:background="
tableConfig.pagination && tableConfig.pagination.background
"
:current-page="requestData.requestParamsOrData.current"
:page-sizes="tableConfig.pageSizeArr"
:page-size="requestData.requestParamsOrData.pageSize"
layout="sizes,prev, pager, next,jumper"
:total="tableMsg.totalCount"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</template>
<style lang="less" scoped>
.clearfix {
display: flex;
justify-content: flex-end;
margin-top: 18px;
}
</style>
myTableMixin.js
export default function (requestData) {
const onHandleSizeChange = (val) => {
requestData.requestParamsOrData = {
...requestData.requestParamsOrData,
pageSize: val,
};
};
const onHandleCurrentChange = (val) => {
requestData.requestParamsOrData = {
...requestData.requestParamsOrData,
current: val,
};
};
return {
onHandleCurrentChange,
onHandleSizeChange,
};
}
使用
先引入myTableMixin.js
// 请求数据
requestData.requestParmasOrData = {
...requestData.requestParmasOrData,
}
目前只封装一个简易版本,后续再扩展其他表格功能... 第一次写文章好紧张,望各位大佬提出宝贵意见!顺便给小弟点点赞,哈哈哈哈哈哈