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 // 遍历使用key
props?: Record<string, any> // 继承 el-table-column 所有属性 & 自定义属性
type?: 'date' // 常用格式的 el-table-column
component?: 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>
更多推荐
所有评论(0)