封装的table:
<template>
<div class="app-table">
<slot name="header" class="app-table-header"></slot>
<el-table
ref="customTable"
:data="tableData"
class="app-table-content"
stripe
:tooltip-effect="tooltipEffect"
:highlight-current-row="highlightCurrentRow"
@selection-change="selectionChange"
@select="selectRows"
@select-all="selectAll"
@row-click="selectRowClick"
:default-expand-all="expandAll"
v-bind="expandObj"
:current-row-key="currentRowKey"
:size="tableSize"
v-loading="loading"
>
<template #empty>
<div class="no-data" v-show="isEmptyData">
<div class="empty-icon"></div>
<div class="empty-text">暂无数据</div>
</div>
</template>
<el-table-column
v-for="column in columns"
:key="column.prop"
:prop="column.prop"
:label="column.label"
:width="column.width"
:min-width="column.minWidth"
:show-overflow-tooltip="column.showOverflowTooltip"
:fixed="column.fixed"
:sortable="column.sortable"
:align="column.align"
>
<!--自定义列头-->
<template #header v-if="column.slotHeader">
<slot :name="column.slotHeader" :column="column"></slot>
</template>
<template #default="scope">
<!--自定义列内容-->
<span v-if="column.slotName">
<slot
:name="column.slotName"
:row="scope.row"
:$index="scope.$index"
:$count="tableData.length"
:$pagination="pagination"
></slot>
</span>
<!--格式化内容-->
<span v-else-if="column.formatter">{{ column.formatter(scope.row, column) }}</span>
<span v-else>
{{ initColValue(scope.row, column.prop) }}
</span>
</template>
</el-table-column>
</el-table>
<el-pagination
v-if="showPage && total"
:small="pagination.small"
:total="total"
:current-page="pagination.currentPage"
:page-sizes="pagination.pageSizes"
:page-size="pagination.limit"
class="app-table-pagination"
:layout="pagination.layout"
@current-change="pageChange"
@size-change="pageSizeSelect"
/>
</div>
</template>
<script lang="ts" setup>
import { computed, ComputedRef, reactive, ref, watch } from 'vue';
interface TableProps {
columns: Table.Column[]; // 每列的配置项
options?: Table.Options;
columnTypes?: string; // 额外表格列,selection/index/expand
service: Function; // 获取table data 方法,需要返回promise
datas: Array<string>;
beforeSearch?: (params: any) => Promise<any>; // 查询table参数处理
afterSearch?: (res: any) => any; // 查询table 结果处理
rowKey?: [String, Function];
expandAll?: Boolean;
expandRowKeys?: [];
showPage?: Boolean;
pageOpt: { small: boolean; limit: number; pageSizes: number; layout: string };
highlightCurrentRow?: Boolean;
currentRowKey?: [String, Number];
tooltipEffect?: String;
rowClick?: Function;
tableSize?: String;
selectRow?: [];
immediateSearch?: Boolean;
}
// 接受父组件参数,配置默认值
const props = defineProps<TableProps>();
// const props = withDefaults(defineProps<TableProps>(), {});
interface EmitEvent {
(e: 'pageChange', current: number): void;
(e: 'pageSizeChange', size: number): void;
(e: 'search'): void; // 重置当前页 重新检索
(e: 'select-row', row: any): void;
(e: 'selection-change', selection: any): void; // 当选择项发生变化时会触发该事件
(e: 'row-click', rows: any): void; // 当某一行被点击时会触发该事件
(e: 'cell-click', row: any, column: any, cell: any, event: Event): void; // 当某个单元格被点击时会触发该事件
(e: 'select-all', row: any): void;
(e: 'size-change', pageSize: number): void; // pageSize事件
(e: 'current-change', currentPage: number): void; // currentPage按钮组事件
}
const emit = defineEmits<EmitEvent>();
let tableData: any = reactive([]);
const isEmptyData = ref<boolean>(false);
const loading = ref<boolean>(false);
let total = ref<number>(0);
const customTable = ref(null);
let rowKeys = props.expandRowKeys ? [...props.expandRowKeys] : [];
// 设置option默认值,如果传入自定义的配置则合并option配置项
const _options: ComputedRef<Table.Options> = computed(() => {
const option = {
stripe: false,
tooltipEffect: 'dark',
showHeader: true,
showPagination: false,
rowStyle: () => 'cursor:pointer', // 行样式
};
return Object.assign(option, props?.options);
});
const pagination = {
small: false,
currentPage: 1,
limit: 10,
pageSizes: [10, 20, 50, 100],
layout: 'total, sizes, prev, pager, next, jumper',
};
watch(
() => props.service,
() => search()
);
watch(
() => props.datas,
() => {
pagination.limit = 10;
pagination.currentPage = 1;
getTableDatas();
},
{ deep: true }
);
const expandObj = computed(() => {
if (props.rowKey) {
return {
'row-key': props.rowKey,
'expand-row-keys': rowKeys,
};
}
return {};
});
const isBackEnd = computed(() => {
return !!props.service;
});
const pageChange = (current: number) => {
pagination.currentPage = current;
emit('pageChange', current);
getTableDatas();
};
const pageSizeSelect = (size: number) => {
pagination.limit = size;
emit('pageSizeChange', size);
search();
};
// 重置当前页 重新检索
const search = (): void => {
pagination.currentPage = 1;
getTableDatas();
};
// 根据当前条件检索
const getTableDatas = (): void => {
// 组装参数
const { limit, currentPage } = pagination;
if (!isBackEnd.value) {
tableData = props.datas.slice((currentPage - 1) * limit, limit * currentPage);
total.value = props.datas.length;
return;
}
const data = {
pageSize: limit,
pageNum: currentPage, // 当前页page数
};
// this.tableData = [];
loading.value = true;
// 查询前处理参数
const params = props.beforeSearch!(data);
props
.service(params)
.then((res: any) => {
console.log('数据----', res);
loading.value = false;
// 重新设置expandRowKeys 不然不会默认展开
if (props.rowKey && rowKeys) {
rowKeys = rowKeys.slice(0);
}
if (total.value === 0) {
isEmptyData.value = true;
} else {
isEmptyData.value = false;
}
})
.catch((err: any) => {
loading.value = false;
console.log(err);
// this.$message.error(err.errorMsg || '获取列表数据出错!');
});
};
const initColValue = (row: any, prop: any) => {
let result = row;
if (prop && prop.indexOf('.') !== -1) {
prop.split('.').forEach((vv: any) => {
result = result[vv];
});
} else {
result = result[prop];
}
return result;
};
const selectionChange = (selection: any) => {
emit('selection-change', selection);
};
const selectRowClick = (rows: any) => {
emit('row-click', rows);
};
const selectRows = (row: any) => {
emit('select-row', row);
};
const selectAll = (row: any) => {
emit('select-all', row);
};
getTableDatas();
</script>
因为我这个封装是将数据和分页都是在组件中处理,只暴露出service即可
页面中使用:
<app-table
:columns="tableIaasColumn"
:service="tableServer"
:limit="6"
:beforeSearch="handleParams"
/>
<script lang="ts" setup>
import { reactive } from 'vue';
import { getIaasList, IaasSearchForm } from '@/pages/admin/service/capacity';
const tableIaasColumn = [
{ prop: 'name', label: '业务名称', align: 'center' },
{ prop: 'businessName', label: '业务名称', align: 'center' },
{ prop: 'type', label: '需求种类', align: 'center' },
{ prop: 'createDate', label: '创建时间', align: 'center' },
{
width: '250',
label: '操作',
align: 'center',
buttons: [
{ name: '查看', type: 'primary', command: 'look' },
{ name: '下载', type: 'success', command: 'down' },
{ name: '删除', type: 'danger', command: 'delete' },
],
},
] as Table.Column[];
const iaasSearchForm = reactive<IaasSearchForm>({
name: '',
businessName: '',
currentPage: 1,
pageSize: 10,
});
type TableServer = () => void;
let tableServer: TableServer = async () => await getIaasList(iaasSearchForm);
const handleParams = (params: any) => {
return {
...params,
...params.value,
};
};
</script>
但是能打印出数据,但是也面没渲染,这是哪里写错了(我也是最近学typescript,搞得很懵逼),有用过typescript大佬帮忙看看怎么写就对了,感谢。
页面上我是这样获取的:
type TableServer = () => void;
let tableServer: TableServer = async () => await getIaasList(iaasSearchForm);
const handleParams = (params: any) => {
return {
...params,
...params.value,
};
};
el-table 需要的的数据 tableData,按照下面代码实现的应该能出来,你的代码没看到给 tableData 赋 service 返回的值呀