vue3中简单二次封装element-table
我们平常都会将element-table封装一次,方便复用,减少不必要的代码。参考ant-design的table组件用法,试着封装了一下。
-
第一种直接使用SFC的vue文件
<template> <el-table style="width: 100%"> <template v-for="item in tableHeader" :key="item.dataIndex"> <el-table-column show-overflow-tooltip v-if="item.slotName || item.render" :prop="item.dataIndex" :label="item.title" :sortable="item.sortable" :align="item.align || null" :width="item.width"> <template #default="scope"> <div v-if="item.render" > {{ item.render({ data: scope.row }) }} </div> <slot v-else :name="item.slotName" :data="scope.row"></slot> </template> </el-table-column> <el-table-column show-overflow-tooltip v-else :prop="item.dataIndex" :label="item.title" :sortable="item.sortable" :align="item.align || null" :width="item.width" /> </template> <slot /> </el-table> </template> <script lang="ts" setup> import { VNodeChild } from 'vue'; interface tableHeaderItem { dataIndex: string title: string slotName?: string align?: string width?: string sortable?: boolean render?: string } const props = defineProps<{ tableData: any, tableHeader: tableHeaderItem[] }>() </script>slotName可以自定义当前列的表格内容以及样式render可以自定义当前列的表格内容
用法如下:
<template> <div class="table"> <NewElTable :data="tableData" :table-header="tableHeader" size="small"> <template #name="{ data }"> <div>{{ data.name }}</div> </template> </NewElTable> </div> </template> <script setup> import NewElTable from "@/components/new-el-table/index.vue" const tableHeader = [ { dataIndex: 'date', title: '日期', }, { dataIndex: 'name', title: '名字', slotName: 'name', }, { dataIndex: 'address', title: '地址', render({ data }) { //在这里可以做一些map解构或者计算 return data.address } } ] const tableData = [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] </script> <style scoped> .table { width: 500px; } </style> -
使用
t/jsx来封装import { defineComponent } from "vue"; import { ElTable, ElTableColumn } from "element-plus"; export default defineComponent({ props: { tableHeader: { type: Array, default: [] } }, setup(props) { const { tableHeader } = props return () => ( <ElTable style="width: 100%"> { tableHeader.map(item => { if (item.render) { return <> <ElTableColumn show-overflow-tooltip prop={item.dataIndex} label={item.title} sortable={item.sortable} align={item.align || null} width={item.width} v-slots={{ default: (scope) => <> { item.render({ data: scope.row }) } </> }}> </ElTableColumn> </> } else if (item.slotName) { return <> <ElTableColumn show-overflow-tooltip prop={item.dataIndex} label={item.title} sortable={item.sortable} align={item.align || null} width={item.width} v-slots={{ default: (scope) => <> {this.$slots.default(scope.row)} </> }}> </ElTableColumn> </> } else { return <ElTableColumn show-overflow-tooltip prop={item.dataIndex} label={item.title} sortable={item.sortable} align={item.align || null} width={item.width}> </ElTableColumn> } }) } </ElTable> ) } })这种方式和上面的区别主要在于
render,可以使用h函数,也可以使用t/jsx抛出的方法,如下://demo.jsx export default function demo({data}) { return ( <> <div>{data.address}</div> </> ) }//app.vue <template> <div class="table"> <NewElTable :data="tableData" :table-header="tableHeader" size="small"> <template #name="{ data }"> <div>{{ data.name }}</div> </template> </NewElTable> </div> </template> <script setup> import NewElTable from "@/components/new-el-table/index.vue" const tableHeader = [ { dataIndex: 'date', title: '日期', }, { dataIndex: 'name', title: '名字', slotName: 'name', render({ data }) { return h('div', { innerHTML: data.name, style: { color: 'red' } }) } }, { dataIndex: 'address', title: '地址', render: demo } ] const tableData = [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] </script> <style scoped> .table { width: 500px; } </style>
最后有个疑惑,就是在第一种里面,如何修改可以让render支持h函数和t/jsx