基于element封装可配置JSON表格组件
话不多说直接贴代码,复制运行即可查看效果
子组件全部代码
<template>
<div class="custom-table">
<el-table
:data="tableData"
border
style="width: 100%"
size="mini"
max-height="800"
v-bind="$attrs"
v-on="$listeners"
highlight-current-row
>
<template v-for="item in config.column">
<!-- 操作 -->
<template v-if="item.type === 'handler'">
<el-table-column
:key="item.prop"
v-bind="item"
align="center"
fixed="right"
>
<template slot-scope="{ row }">
<el-button
v-for="btn in item.btns"
:key="btn.label"
type="text"
@click="handelClick($event, btn.click, row)"
:icon="btn.icon"
>
<!-- {{ btn.label }} -->
</el-button>
</template>
</el-table-column>
</template>
<!-- 自定义slot -->
<template v-else-if="item.type === 'custom'">
<el-table-column :key="item.prop" v-bind="item" align="center">
<template slot-scope="scope">
<slot :name="item.slotName" v-bind="scope" :prop="item.prop" />
</template>
</el-table-column>
</template>
<!-- 默认 -->
<template v-else>
<el-table-column
:key="item.prop"
v-bind="item"
align="center"
:show-overflow-tooltip="true"
/>
</template>
</template>
</el-table>
<!-- 分页 -->
<el-pagination
v-if="config.usePagination"
background
small
layout="prev, pager, next"
style="text-align: center; margin-top: 10px"
:current-page="config.paginationData.currentPage"
:page-size="config.paginationData.pageSize"
:total="config.paginationData.total"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</template>
<script>
export default {
props: {
config: {
type: Object,
default() {
return {
column: [],
paginationData: {
pageSize: 20,
currentPage: 1,
total: 0,
},
};
},
required: true,
},
tableData: {
type: Array,
default() {
return [];
},
},
},
mounted() {
console.log(this.config, "config");
},
methods: {
handelClick(e, click, row) {
e.stopPropagation();
this.$emit(click, row);
},
handleCurrentChange(val) {
this.$emit("currentChange", val);
},
},
};
</script>
<style lang="scss" scoped></style>
父组件使用
<template>
<div>
<el-button @click="getData">data</el-button>
<CustomTable
size="mini"
v-loading="loading"
:config="tableConfig"
:table-data="tableData"
@row-click="handleRowClick"
@selection-change="selectionChange"
@handelEditClick="handelEditClick"
@handelTeamEditClick="handelTeamEditClick"
@deleteItemClick="deleteItemClick"
@currentChange="handleCurrentChange"
>
<template #inputEdit="{ row }">
<el-input
v-model="row.inputValue"
placeholder="please input"
size="small"
></el-input>
</template>
<template #artcleName="{ row }">
<el-tag v-for="item in row.artcleName" :key="item.id" size="small">
{{ item.name }}
</el-tag>
</template>
</CustomTable>
</div>
</template>
<script>
import tableConfig from "./config";
import CustomTable from "@/components/CustomTable/index.vue";
export default {
components: {
CustomTable,
},
data() {
return {
loading: false,
tableConfig,
tableData: [
{
id: 1,
text: "test",
title: "test",
admin: "guanliyuan ",
category: "小白",
inputValue: "Context",
artcleName: [
{ id: 1, name: "Context" },
{ id: 2, name: "标签" },
],
},
],
};
},
created() {
this.tableData = this.generateRandomData(50);
this.tableConfig.paginationData.total = this.tableData.length;
},
methods: {
getData() {
console.log(this.tableData, "表格数据");
},
generateRandomData(count) {
const categories = ["小白", "中级", "高级", "专家", "初学者"];
const admins = ["guanliyuan", "administrator", "admin", "user", "tester"];
const texts = ["test", "example", "sample", "demo", "testcase"];
const titles = [
"Test Title",
"Example Title",
"Sample Title",
"Demo Title",
"Testcase Title",
];
const randomElement = (arr) =>
arr[Math.floor(Math.random() * arr.length)];
const randomString = (length) =>
Math.random()
.toString(36)
.substring(2, length + 2);
return Array.from({ length: count }, (_, index) => ({
id: index + 1,
text: randomElement(texts),
title: randomElement(titles),
admin: randomElement(admins),
category: randomElement(categories),
inputValue: randomString(8),
artcleName: Array.from({ length: 2 }, (_, nameIndex) => ({
id: nameIndex + 1,
name: randomString(5),
})),
}));
},
handleRowClick(val) {
console.log(val, "点击行");
},
selectionChange(val) {
console.log(val, "勾选");
},
handelEditClick(row) {
console.log(row, "编辑");
},
handelTeamEditClick(row) {
console.log(row, "团队编辑");
},
deleteItemClick(row) {
console.log(row, "删除");
},
handleCurrentChange(val) {
this.tableConfig.paginationData.currentPage = val;
console.log(val, "当前页");
},
},
};
</script>
可配置文件 js
放置同级位置
const tableConfig = {
//type 区分操作类型 normal:普通 handler:操作 custom:自定义插槽
column: [
{ type: "selection", width: 60, align: "center" },
{
type: "normal",
prop: "text",
label: "KeyWords",
width: 200,
},
{ type: "normal", prop: "title", label: "Title" },
{
type: "normal",
prop: "category",
label: "Category",
width: 150,
},
{
type: "normal",
prop: "admin",
label: "Admin",
width: 200,
},
{
type: "handler",
label: "Controls",
width: 150,
btns: [
{
label: "Edit",
click: "handelEditClick",
icon: "el-icon-edit",
},
{
label: "TeamEdit",
click: "handelTeamEditClick",
icon: "el-icon-s-open",
},
{
label: "Delete",
click: "deleteItemClick",
icon: "el-icon-delete",
},
],
},
{
type: "custom",
label: "Input",
prop: "inputValue",
slotName: "inputEdit",
},
{
type: "custom",
label: "artcleName",
prop: "artcleName",
slotName: "artcleName",
},
],
usePagination: true,
paginationData: {
pageSize: 20,
currentPage: 1,
total: 0,
},
};
export default tableConfig;