记录一下动态组件的封装,方便下次使用
上代码 !
<template>
<el-table v-bind="attrs" :height="tableHeight" v-loading="loading" :data="tableData" border>
<el-table-column
v-for="column in columns"
:key="column.prop"
:label="column.label"
v-bind="getColumnOptions(column)"
>
<template #default="scope">
<!-- 支持组件/函数/插槽三种渲染方式 -->
<slot v-if="column.slot" :name="column.slot" v-bind="{ ...scope }" />
<component v-else-if="column.render" :is="column.render" v-bind="{ ...scope }" />
</template>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
import { ElTable, ElTableColumn } from 'element-plus'
import { DefineComponent } from 'vue'
export type DynamicTableColumn = Partial<InstanceType<typeof ElTableColumn>> & {
/**
* 自定义渲染函数
* @example
* ```html
* import { Fragment } from 'vue'
*<Fragment>
* <ElButton
* onClick={() => {
* console.log(`e ==>`, row)
* }}
* link
* type="warning"
* >
* 编辑
* </ElButton>
* <ElButton link type="danger">
* 删除
* </ElButton>
*</Fragment>
* ```
* @param scope
*/
render?: (scope: { row: AnyObject; column: AnyObject; $index: number }) => DefineComponent
/**
* 是否使用插槽&对应插槽名称 如 slot:'name'
* @example
* ```vue
* <template #name={xxx}>
*
* </template>
* ```
*/
slot?: string
type?: 'selection' | 'index'
align?: 'left' | 'center' | 'right'
}
type IProps = {
tableData: any[]
loading: boolean
tableHeight: number
columns: DynamicTableColumn[]
}
const props = withDefaults(defineProps<IProps>(), {
tableHeight: 500,
})
console.log(`props ==>`,props);
type IEmit = {
(e: 'selection-change', rows: any[]): any
}
const emit = defineEmits<IEmit>()
// 获取所有非 props 的属性和事件监听器
const attrs = useAttrs()
const slots = useSlots()
const getColumnOptions = (column: DynamicTableColumn): DynamicTableColumn => {
return {
...column,
align: column.align ? column.align : 'center',
showOverflowTooltip: !column.showOverflowTooltip && !column.type ? true : false,
}
}
</script>
<style lang="scss" scoped></style>
页面使用
<template>
<div class="w-full h-full overflow-hidden p-[20px] pt-0">
<ProTable>
<template #table="{ tableHeight }">
<DynamicTable
:tableHeight="tableHeight"
:tableData="tableData"
:loading="loading"
:columns="columns"
@selection-change="(rows) => (tableCheck = rows)"
>
<template #option>
<el-button link :type="buttonType.edit">编辑</el-button>
<el-button link :type="buttonType.delete">删除</el-button>
</template>
</DynamicTable>
</template>
<template #pagination>
<pagination
v-model:page="queryParams.page"
v-model:limit="queryParams.page_size"
:total="total"
:pageSizes="elConfig.pageSizes"
small
background
:layout="elConfig.layout"
@pagination="getList"
/>
</template>
</ProTable>
</div>
</template>
<script lang="tsx" setup>
import ProTable from '@/components/ProTable/index.vue'
import { handleTableIndex } from '@/utils/handleTableIndex'
import { Fragment } from 'vue'
/**表格数据 */
const tableData = ref<any[]>([])
const tableCheck = ref<any[]>([])
const columns = ref<DynamicTableColumn[]>([
{ type: 'selection', width: '50', align: 'center' },
{
label: '序号',
width: '60',
prop: '',
formatter: (row, column, cellValue, index) => {
return handleTableIndex(index, queryParams.page, queryParams.page_size) + ''
},
},
{ label: '用户编号', prop: '' },
{ label: '用户名称', prop: '' },
{ label: '用户地址', prop: '' },
{ label: '用户分类', prop: '' },
{
label: '来源',
prop: '',
render() {
return (
<Fragment>
<ElButton
onClick={() => {
console.log(`e ==>`, row)
}}
link
type="warning"
>
编辑
</ElButton>
<ElButton link type="danger">
删除
</ElButton>
</Fragment>
)
},
},
{ label: '标签名称', prop: '' },
{ label: '运行容量', prop: '' },
{ label: '合同容量', prop: '' },
{ label: '用能类型', prop: '' },
{ label: '供电所', prop: '' },
{ label: '创建时间', prop: '' },
{ label: '操作', slot: 'option' },
])
</script>
<style lang="scss" scoped></style>