今天在学习使用element-plus的虚拟化表格时,遇到了一个问题,就是需要在表格项中自定义渲染内容(比如渲染一个Tag标签,渲染一个下拉框组件等) 可见官网示例:Virtualized Table 虚拟化表格 | Element Plus (element-plus.org)
关于jsx / tsx 可以自行搜索相关文档去学习,我是因为之前学习过react所以了解。
但是官方给的示例中,只示例了一些普通的组件的使用,并没有告诉如何使用插槽(原本在vue的template中写,是直接写template插槽即可,但是在tsx中不能这么写)。经过多方查找,终于找到了方法,就是在组件标签中有个v-slots属性,给里面传入一个对象,键是插槽名,值是render函数。
比如element-plus中的Popover组件,就有两个插槽,一个是默认插槽,一个是具名插槽。要想在tsx中使用,需要这样:
下面这个是在vue的template标签中的写法。
<template>
<el-popover :width="300" >
<template #reference>
这里是普通内容
</template>
<template #default>
这里是悬浮之后,弹出的提示框的内容
</template>
</el-popover>
</template>
但是在tsx中,不能这样写,会报错。我们需要这样:
<script lang="tsx" setup>
import { Column, ElPopover } from 'element-plus';
const columns: Column<any>[] = [
{
key: 'id',
title: '',
dataKey: 'id',
width: 40,
align: 'center',
cellRenderer: ({ cellData: id }) => (
<ElPopover width={300} v-slots={{
reference: () => <div>这里是普通内容</div>,
default: () => <div>这里是悬浮之后,弹出的提示框的内容</div>
}}>
</ElPopover>
)
}
]
</script>
解释 及 tsx的注意事项:
1. 首先注意script标签的 lang 写的是 tsx 或 jsx,才能在里面写tsx代码。
2. 和vue不一样的是,在jsx / tsx中,想使用变量是单花括号 { xxx } (vue是双花括号 {{ }} 或者属性前加上冒号)。所以在v-slots属性中,虽然用了双括号,但是实际上传递的其实是一个对象,里面写的东西要遵循对象的写法(键值对)。v-slots中:键是插槽名,值是render函数
3. 组件名不能用 el-popover 的写法,需要使用双驼峰命名法 ElPopover
4. tsx中给事件绑定函数,使用 onXxxx = { } 的写法,比如onClick={ },括号里面写函数的名字(不是字符串)。如果想传递参数,则这样写 onClick={ () => xxx(id) }。传递一个高阶的箭头函数。
下面给出我用element-plus的虚拟化表格的代码示例 (基于Nuxt3,所以额外嵌套了一个client-only标签)
<template>
<div class="list">
<client-only>
<el-table-v2 :columns="columns" :data="list" :width="1300" :height="600"/>
</client-only>
</div>
</template>
<script lang="tsx" setup>
import { ElDropdown, ElDropdownMenu, ElTag, ElTooltip, ElDropdownItem, } from 'element-plus'
import { Loading as LoadingIcon } from '@element-plus/icons-vue'
import type { Column } from 'element-plus'
/**表头数据 */
const columns: Column<any>[] = [
{
key: '_name',
title: '歌名',
dataKey: '_name',
width: 500,
},
{
key: '_artists',
title: '歌手',
dataKey: '_artists',
width: 275,
},
{
key: '_album',
title: '专辑',
dataKey: '_album',
width: 275,
},
{
key: 'fee',
title: '标签',
dataKey: 'fee',
width: 100,
align: 'center',
cellRenderer: ({ cellData: fee }) => (
<ElTooltip content={fee === 0 ?
'免费' : fee === 1 ?
'VIP' : fee === 4 ?
'专辑' : '可听'}>
{
fee === 0 ?
<ElTag type="success">免费</ElTag> : fee === 1 ?
<ElTag type="warning">VIP</ElTag> : fee === 4 ?
<ElTag type="info">专辑</ElTag> : <ElTag type="success">可听</ElTag>
}
</ElTooltip>
),
},
{
key: '_time',
title: '时长',
dataKey: '_time',
width: 70,
},
{
key: 'id',
title: '',
dataKey: 'id',
width: 40,
cellRenderer: () => <ElDropdown v-slots={{
dropdown: ({ cellData: id }: { cellData: number }) => <ElDropdownMenu>
<ElDropdownItem onClick={() => del(id)}>
删除
</ElDropdownItem>
<ElDropdownItem disabled>待添加</ElDropdownItem>
</ElDropdownMenu>
}}>
<span style={{ color: 'var(--center-color)' }}>...</span>
</ElDropdown>
},
]
const del = (id: number)=>{ }
/** 测试列表 */
const list: Array<tableData> = [
{
_name: '歌曲名',
_album: '专辑名',
_artists: '歌手名',
_time: '时长'
id: 0,
fee: 0
}
]
</script>