1. 创建文件夹 tableComponent / index.vue / tableRender.vue
index.vue
<template>
<el-table :data="data" border tableLayout="fixed">
<template v-for="(column, index) in columns" :key="index">
<el-table-column
:prop="column.prop"
:label="column.label"
v-if="!column.render"
>
</el-table-column>
<el-table-column :label="column.label" v-if="column.render">
<template #default="scope">
<Render
:renderDom="
() => {
return column.render(scope);
}
"
/>
</template>
</el-table-column>
</template>
<el-table-column label="操作" width="180" fixed="right">
<template #default="scope">
<el-button
v-for="(action, index) in rowActions"
:key="index"
:type="action.type"
@click="action.handler(scope.row)"
>
{{ action.label }}
</el-button>
</template>
</el-table-column>
<template v-slot:empty>
<el-empty :image-size="200" />
</template>
</el-table>
<div class="table-pagination">
<el-pagination
v-model:current-page="currentPage2"
v-model:page-size="pageSize2"
:page-sizes="[100, 200, 300, 400]"
:small="small"
:disabled="disabled"
:background="background"
layout="sizes,total, ->, prev, pager, next, jumper"
:total="400"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from "vue";
import Render from "./render.vue";
interface Column {
prop: string;
label: string;
render?: (row: any) => string;
}
interface RowAction {
label: string;
type: string;
handler: (row: any) => void;
}
export default defineComponent({
name: "CustomTable",
components: {
Render,
},
props: {
data: {
type: Array,
required: true,
},
columns: {
type: Array as () => Column[] | any,
required: true,
},
rowActions: {
type: Array as () => RowAction[] | any,
required: true,
},
},
emits: ["onChangePage", "onChangeLimit"],
setup(_props, { emit }) {
const currentPage2 = ref(4); //当前页码
const pageSize2 = ref(10); // 每页条数
const disabled = ref(false);
const small = ref(false);
const background = ref(false);
const handleSizeChange = (val: number) => {
emit("onChangeLimit", val);
console.log(`${val} 每页显示多少条`);
};
const handleCurrentChange = (val: number) => {
emit("onChangePage", val);
console.log(`当前页: ${val}`);
};
return {
pageSize2,
currentPage2,
handleSizeChange,
handleCurrentChange,
disabled,
small,
background,
};
},
});
</script>
<style lang="scss">
.table-pagination {
box-sizing: border-box;
width: 100%;
max-width: 100%;
padding: 13px 15px;
background-color: #fafafa;
// justify-content: center;
}
</style>
2. render.vue
<template></template>
<script lang="ts">
import { defineComponent, h, PropType, VNode } from "vue";
interface RenderProps {
renderDom: (hFunc: typeof h) => VNode;
}
export default defineComponent({
name: "Render",
props: {
renderDom: {
type: Function as PropType<(hFunc: typeof h) => VNode>,
required: true,
},
},
setup(props: RenderProps) {
// return () => h("div", {}, props.renderDom(h));
return props.renderDom;
},
});
</script>
3. 页面中使用
<template>
<div class="table">
<CustomTable
:data="tableData"
:columns="tableColumns"
:rowActions="tableActions"
/>
</div>
</template>
<script lang="ts">
import { defineComponent, h, ref } from "vue";
import CustomTable from "@/components/tableComponent/index.vue";
import { ElSwitch } from "element-plus";
export default defineComponent({
name: "MyPage",
components: {
CustomTable,
},
setup() {
//表格数据
const tableData = ref([
{ id: 1, name: "John", age: 30, status: true },
{ id: 2, name: "Jane", age: 25, status: true },
{ id: 3, name: "Bob", age: 35, status: true },
]);
//表头
const tableColumns: any = [
{ prop: "id", label: "ID" },
{ prop: "name", label: "用户名" },
// 普通的html元素
// return h(
// "span",
// {
// class: "my-component",
// style: { color: "red" }, //可动态
// },
// scope.row.age
// );
// element的
render: (scope: any) => {
return h(ElSwitch, {
modelValue: scope.row.status,
"inline-prompt": true,
"active-text": "是",
"inactive-text": "否",
"active-value": 1,
"inactive-value": 0,
size: "large",
"onUpdate:modelValue": (value: string | boolean | any) => {
scope.row.status = value;
// 这里可以处理其他逻辑
},
});
},
},
];
//操作栏
const tableActions = [
{
label: "编辑",
type: "primary",
handler: (row: Object) => handleEdit(row),
},
{
label: "删除",
type: "danger",
handler: (row: Object) => handleDelete(row),
},
];
const handleEdit = (row: Object) => {
console.log("Edit row:", row);
};
const handleDelete = (row: Object) => {
console.log("Delete row:", row);
};
return {
tableData,
handleEdit,
handleDelete,
tableActions,
tableColumns,
};
},
});
</script>