在Vue3中使用 tsx / jsx + 插槽 (element-plus中的tsx写法与插槽)

        今天在学习使用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>

猜你喜欢

转载自blog.csdn.net/m0_64130892/article/details/131638404