前言
支持动态传入列,列内容可以指定插槽,指定格式化显示
样式没太写,主要分享基础功能封装
效果
Table组件代码BaseTable.vue
<template><el-table :data="data" border><template v-for="col in columns" :key="col.prop"><el-table-column :prop="col.prop" :label="col.label" :width="col.width" show-overflow-tooltip><template #default="{ row }"><slot v-if="col.slot" :name="col.slot"></slot><!-- 因为这个内容不是通过表格的prop直接绑定的,所以表格自带的溢出省略号失效,自己写下 --><div v-else class="text-overflow">{{ getFormatter(col, row[col.prop]) }}</div></template></el-table-column></template></el-table><br><template v-if="isShowPage"><el-pagination v-model:currentPage="currentPage1" v-model:page-size="pageSize1" :page-sizes="[10, 20, 30, 40]"background layout="total, sizes, prev, pager, next, jumper" :total="totalSize" @size-change="sizeChange"@current-change="currentChange" /></template>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';export interface BaseTableConfig {data: any[];columns: TableColumn[];current?: number;pageSize?: number;totalSize?: number;[key: string]: any;
}
export interface TableColumn {prop?: string;label: string;slot?: string;width?: number;formatter?: Function;[key: string]: any;
}
const emit = defineEmits(['update:pageSize', 'update:currentPage', 'pageChange'])
const props = defineProps({data: {type: Array,default: () => ([])},columns: {type: Array<any>,default: () => ([])},currentPage: {type: Number,default: 1,},pageSize: {type: Number,default: 10,},totalSize: {type: Number,default: 0,},isShowPage: {type: Boolean,default: true,}
});
const currentPage1 = ref(props.currentPage);
const pageSize1 = ref(props.pageSize);
const getFormatter = (col: any, value: any) => {if (col.formatter) {return col.formatter(value);}return value;
}
const sizeChange = (val: number) => {emit('update:pageSize', val);emit('pageChange');
}
const currentChange = (val: number) => {emit('update:currentPage', val);emit('pageChange');
}
</script>
<style scoped>
.text-overflow {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;
}
</style>
页面中使用组件
<template><div>总条数:{{ tbConfig.totalSize }};当前页:{{ tbConfig.current }};每页条数:{{ tbConfig.pageSize }}</div><BaseTable :data="tbConfig.data" :columns="tbConfig.columns" v-model:currentPage="tbConfig.current"v-model:pageSize="tbConfig.pageSize" :totalSize="tbConfig.totalSize" @pageChange="pageClick"><template #avatar="{ row }">这一列用插槽自定义内容{{ row?.avatar }}</template><template #op><el-button type="danger">删除</el-button></template></BaseTable>
</template>
<script lang="ts" setup>
import { reactive } from 'vue';
import { BaseTableConfig, TableColumn } from './BaseTable.vue';
import BaseTable from './BaseTable.vue';const tbConfig: BaseTableConfig = reactive({data: [{ id: 1, name: 'Ahsh', avatar: 'img1.png', ifKey: true },{ id: 2, name: 'Rjjds', avatar: 'img2.png', ifKey: false },{ id: 3, name: 'Ukkd特别长长长长长长长长长长的名字', avatar: 'img3.png', ifKey: true },],columns: <TableColumn[]>[{ prop: 'id', label: '序号', width: 100 },{ prop: 'name', label: '名称', width: 200 },{ prop: 'avatar', label: '图标', slot: 'avatar', width: 200 },{ prop: 'ifKey', label: '是否开放', formatter: formatBoolean },{ label: '操作', slot: 'op' },],current: 1,pageSize: 10,totalSize: 0,
});function formatBoolean(val: Boolean) {return val ? '是' : '否';
}function pageClick() {// TODO监听到当前页或者每页条数变化,重新查询列表console.log('get-data');
}
</script>
<style scoped></style>