表格组件的简单封装
将表单改写成通过数组形式渲染,直接上代码
将表单改写成通过数组形式渲染,直接上代码
<template>
这里是表格示例
<LeeTable
:table-data="tableData"
:table-columns="columns"
:show-action="true"
:show-pagination="true"
:total="100"
@page-change="handlePageChange"
>
<!-- 自定义列内容 -->
<template #status="{ row }">
<el-tag :type="row.status === 'success' ? 'success' : 'danger'">
{{ row.status }}
</el-tag>
</template>
<!-- 自定义操作列内容 -->
<template #address="{ row }">
<el-input v-if="row._isEdit" v-model="row.address"></el-input>
<div v-else>{{ row.address }}</div>
</template>
</LeeTable>
</template>
<script lang="ts" setup>
import { reactive } from "vue";
const tableData = reactive([{
id: 1,
name: '张三',
age: 20,
status: 'success',
address: '北京'
},{
id: 2,
name: '李四',
age: 20,
status: 'danger',
address: '上海'
},{
id: 3,
name: '王五',
age: 20,
status: 'success',
address: '广州'
},{
id: 4,
name: '赵六',
age: 20,
status: 'danger',
address: '深圳'
}])
const columns = reactive([{
prop: 'id',
label: 'ID',
width: 100
},{
prop: 'name',
label: '姓名',
width: 100
},{
prop: 'age',
editType: 'ElInputNumber',
label: '年龄',
editProps: { min: 0, max: 100 },
width: 180
},{
prop: 'status',
label: '状态',
renderType: 'slot',
width: 100
},{
prop: 'address',
label: '地址插槽',
renderType: 'slot',
editType: 'slot',
width: 100
},{
prop: '',
renderType: 'operation',
buttons: [{
label: '编辑',
type: 'primary',
onClick: (row: any) => {
console.log(row)
row._isEdit = true
}
},{
label: '删除',
type: 'danger'
}],
label: '操作',
width: 200
}])
const handlePageChange = (page: number) => {
console.log(page)
}
</script>
<template>
<el-table
:data="tableData"
style="width: 100%"
v-loading="loading"
:border="border"
:stripe="stripe"
v-on="$attrs"
>
<el-table-column
v-for="item in tableColumns"
:fixed="item.fixed"
:prop="item.prop"
:label="item.label"
:width="item.width || 180"
:key="item.prop"
>
<template #default="{row}">
<slot v-if="item.renderType === 'slot'" :name="item.prop" :row="row">
</slot>
<template v-else-if="!row._isEdit || !item.editType">
<span v-if="item.renderType !== 'operation'">{{ row[item.prop] }}</span>
<!-- 操作列 -->
<span v-else>
<el-button v-for="(btn, index) in item.buttons" :key="index" :type="btn.type" :size="btn.size" :plain="btn.plain" @click="btn.onClick(row)">
{{ btn.label }}
</el-button>
</span>
</template>
<!-- 编辑内容 -->
<template v-else>
<slot v-if="item.editType === 'slot'" :name="item.prop" :row="row">
</slot>
<component :is="handleComponent(item.editType)" v-model="row[item.prop]" v-bind="item.editProps"></component>
</template>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-if="showPagination"
class="mt-4"
background
layout="prev, pager, next"
:total="total"
:page-size="pageSize"
:current-page="currentPage"
@current-change="handlePageChange"
/>
</template>
<script lang="ts" setup>
import { type TableData, type TableColumns } from "@/types/types"
import { ElInputNumber, ElInput, ElSelect, ElDatePicker, ElRadioGroup, ElSwitch, ElCheckboxGroup, ElCascader } from 'element-plus';
interface Props {
tableData: TableData
tableColumns: TableColumns
loading?: boolean
border?: boolean
stripe?: boolean
showPagination?: boolean
total?: number
pageSize?: number
currentPage?: number
}
const props = withDefaults(defineProps<Props>(), {
tableData: () => [],
tableColumns: () => [],
loading: false,
border: true,
stripe: true,
showPagination: false,
total: 0,
pageSize: 10,
currentPage: 1
})
const emit = defineEmits(['page-change'])
const handlePageChange = (page: number) => {
emit('page-change', page)
}
const handleComponent = (renderType:string) => {
switch (renderType) {
case 'ElInput':
return ElInput
case 'ElInputNumber':
return ElInputNumber
case 'ElSelect':
return ElSelect
case 'ElDatePicker':
return ElDatePicker
case 'ElRadioGroup':
return ElRadioGroup
case 'ElSwitch':
return ElSwitch
case 'ElCheckboxGroup':
return ElCheckboxGroup
case 'ElCascader':
return ElCascader
default:
return renderType
}
}
</script>
<template>
这里是表格示例
<leeVxeTable :table-data="tableData" :columns="columns">
<!-- 自定义列内容 -->
<template #status="{ row }">
<el-tag :type="row.status === 'success' ? 'success' : 'danger'">
{{ row.status }}
</el-tag>
</template>
<!-- 自定义操作列内容 -->
<template #address="{ row }">
<el-input v-if="row._isEdit" v-model="row.address"></el-input>
<div v-else>{{ row.address }}</div>
</template>
</leeVxeTable>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
const tableData = reactive([
{
id: 1,
name: '张三',
age: 20,
status: 'success',
address: '北京',
height: 175,
weight: 120
},
{
id: 2,
name: '李四',
age: 20,
status: 'danger',
address: '上海',
height: 180,
weight: 110
},
{
id: 3,
name: '王五',
age: 20,
status: 'success',
address: '广州'
},
{
id: 4,
name: '赵六',
age: 20,
status: 'danger',
address: '深圳'
}
])
const columns = reactive([
{
field: 'id',
title: 'ID',
width: 100
},
{
field: 'name',
title: '姓名',
width: 100
},
{
field: 'age',
editType: 'ElInputNumber',
title: '年龄',
editProps: { min: 0, max: 100 },
width: 180
},
{
field: 'status',
title: '状态',
renderType: 'slot',
width: 100
},
{
field: 'address',
title: '地址插槽',
renderType: 'slot',
editType: 'slot',
width: 100
},
{
field: 'heightAndWeight',
title: '体型',
children: [
{
field: 'height',
title: '身高',
width: 100
},
{
field: 'weight',
title: '体重',
width: 100
}
],
width: 100
},
{
field: '',
renderType: 'operation',
buttons: [
{
label: '编辑',
type: 'primary',
onClick: (row: any) => {
console.log(row)
row._isEdit = true
}
},
{
label: '删除',
type: 'danger'
}
],
title: '操作',
width: 200
}
])
</script>
<template>
<div>
<vxe-table
border
show-overflow
height="600"
:scroll-y="{enabled: true, gt: 0}"
:data="tableData">
<template v-for="(item, index) in columns" :key="index">
<template v-if="item.children">
<vxe-colgroup :title="item.title">
<vxe-column v-for="(item2, index2) in item.children" :type="item2.type" :width="item2.width" :key="index2" :field="item2.field" :title="item2.title">
<template #default="{ row }">
<slot v-if="item2.renderType === 'slot'" :name="item2.field" :row="row">
</slot>
<template v-else-if="!row._isEdit || !item2.editType">
<span v-if="item2.renderType !== 'operation'">{{ row[item2.field] }}</span>
<!-- 操作列 -->
<!-- <span v-else>
<el-button v-for="(btn, index) in item.buttons" :key="index" :type="btn.type" :size="btn.size" :plain="btn.plain" @click="btn.onClick(row)">
{{ btn.label }}
</el-button>
</span> -->
</template>
<!-- 编辑内容 -->
<template v-else>
<slot v-if="item2.editType === 'slot'" :name="item2.field" :row="row">
</slot>
<component :is="handleComponent(item.editType)" v-model="row[item2.field]" v-bind="item2"></component>
</template>
</template>
</vxe-column>
</vxe-colgroup>
</template>
<template v-else>
<vxe-column :type="item.type" :width="item.width" :key="index" :field="item.field" :title="item.title">
<template #default="{ row }">
<slot v-if="item.renderType === 'slot'" :name="item.field" :row="row">
</slot>
<template v-else-if="!row._isEdit || !item.editType">
<span v-if="item.renderType !== 'operation'">{{ row[item.field] }}</span>
<!-- 操作列 -->
<span v-else>
<el-button v-for="(btn, index) in item.buttons" :key="index" :type="btn.type" :size="btn.size" :plain="btn.plain" @click="btn.onClick(row)">
{{ btn.label }}
</el-button>
</span>
</template>
<!-- 编辑内容 -->
<template v-else>
<slot v-if="item.editType === 'slot'" :name="item.field" :row="row">
</slot>
<component :is="handleComponent(item.editType)" v-model="row[item.field]" v-bind="item"></component>
</template>
</template>
</vxe-column>
</template>
</template>
</vxe-table>
</div>
</template>
<script lang="ts" setup>
import { type TableData, type TableColumns } from "@/types/types"
import { ElInputNumber, ElInput, ElSelect, ElDatePicker, ElRadioGroup, ElSwitch, ElCheckboxGroup, ElCascader } from 'element-plus';
interface Props {
tableData: TableData
columns: TableColumns
}
const props = withDefaults(defineProps<Props>(), {
tableData: () => [],
columns: () => [],
})
const handleComponent = (renderType:string) => {
switch (renderType) {
case 'ElInput':
return ElInput
case 'ElInputNumber':
return ElInputNumber
case 'ElSelect':
return ElSelect
case 'ElDatePicker':
return ElDatePicker
case 'ElRadioGroup':
return ElRadioGroup
case 'ElSwitch':
return ElSwitch
case 'ElCheckboxGroup':
return ElCheckboxGroup
case 'ElCascader':
return ElCascader
default:
return renderType
}
}
// interface RowVO {
// id: number
// name: string
// role: string
// sex: string
// age: number
// address: string
// }
// const tableData = ref<RowVO[]>([])
// // 模拟行数据
// const loadList = (size = 200) => {
// const dataList: RowVO[] = []
// for (let i = 0; i < size; i++) {
// dataList.push({
// id: 10000 + i,
// name: 'Test' + i,
// role: 'Developer',
// sex: '男',
// age: 40,
// address: 'Address'
// })
// }
// tableData.value = dataList
// }
// loadList(500)
</script>
githuab地址为:'https://github.com/leezhenwang/vue3-TypeScript-demo.git/