Vue3 通过JSON渲染el-table-column生成完整el-table
功能实现背景
通过Vue3实现后台管理项目一定含有表格功能,基于简单的字段渲染有时候想通过JSON配置来提高开发效率
注意:
1.项目依赖element-plus
使用规则
ColumnRenderProp
中key
用于:v-for
需要的唯一标识ColumnRenderProp
中props
用于:继承el-table-column
所有属性 & 自定义属性ColumnRenderProp
中type
用于:常在项目中出现且需要转换的字段如时间、钱等等,可自行追加ColumnRenderProp
中Component
用于:自定义组件ColumnRenderProp
中render
用于:自定义渲染函数- columns中优先级排序 component < render < type < props
项目代码
- 创建
type/index.ts
文件
export interface ColumnRenderProp {key?: string // 遍历使用keyprops?: Record<string, any> // 继承 el-table-column 所有属性 & 自定义属性type?: 'date' // 常用格式的 el-table-columncomponent?: Component // 自定义组件render?: Function // 渲染函数
}
- 创建
ColumnRender.vue
文件
<template><!-- key渲染优先级: column.key > column.props.prop > index--><template v-for="(column, index) in columns" :key="column.key || column.props?.prop || index"><!-- 优先:component --><component v-if="column.component" :is="column.component" v-bind="column.props" /><!-- 其次:render --><el-table-column v-else-if="column.render" v-bind="column.props"><template v-slot="props"><component :is="column.render(props)" /></template></el-table-column><!-- 日期 --><el-table-column v-else-if="column.type === 'date'" v-bind="column.props"><template v-slot="{ row }: { row: any }"><div>{{ parseTime(row[column.props?.prop]) || EMPTYDESC }}</div></template></el-table-column><el-table-column v-else v-bind="column.props" /></template>
</template><script setup lang="ts">
import type { ColumnRenderProp } from '@/types/index.ts'defineOptions({name: 'IPSColumnRender'
})defineProps<{columns: ColumnRenderProp[]
}>()// 时间格式化 => 需自己实现
function parseTime(val: number) {return val
}
</script>
- 创建
ColumnState.vue
文件 => 自定义组件
<template><el-table-column v-bind="$attrs"><template v-slot="{ row }"><div class="el-primary">{{ row.state }}</div></template></el-table-column>
</template>
- 创建
ColumnHandle.vue
文件 => 自定义组件
<template><el-button type="primary" @click="handleDetail">{{ deleteVal }}</el-button>
</template>
<script setup lang="ts">
const props = defineProps<{deleteVal: string,row: any
}>()
const emit = defineEmits<{(e: 'detail', value: any): void
}>()function handleDetail() {console.log('handleDetail', props.row)emit('detail', 123)
}
</script>
- 实现代码
<template><el-table :data="tableData" style="width: 100%"><ColumnRender :columns="columns" /></el-table>
</template><script setup lang="ts">
import ColumnRender from './ColumnRender.vue'
import ColumnState from './ColumnState.vue'
import ColumnHandle from './ColumnHandle.vue'import { computed, h } from 'vue'const tableData = [{name: '张三',state: '已完成',date: '2019-05-03',address: 'No. 189, Grove St, Los Angeles',},{name: '王五',state: '已下单',date: '2019-05-03',address: 'No. 189, Grove St, Los Angeles',}
]// 如果里面数据不会发生改变,可以移除 computed
const columns = computed(() => [{// 普通渲染模式props: {label: '姓名',prop: 'name',width: '180'}},{// 组件渲染模式key: 'state',props: {label: '状态',width: '180'// 此处可以接收组件自定义事件,也可以给组件传递props},component: ColumnState},{// 自定义渲染模式 => 可接收内部事件key: 'handle',props: {label: '操作',width: '180'},render({ row }: { row: any }) {return h(ColumnHandle, {row: row,deleteVal: '详情1',onDetail(val: any) {console.log(val, row.name, '22==')}})}}
])
</script>