表格 Slot 传参的需求场景
在封装表格组件时,经常需要在列定义中传递自定义渲染内容。Element Plus 的 el-table 提供了两种方式来自定义列内容:
- 通过
el-table-column的 slot:直接在列标签内插入模板 - 通过 column 配置对象:在 JavaScript 中定义列,配合渲染函数
问题是:如何在两种模式下统一处理 Slot 传参?
方案一:基于 el-table-column 的 Slot
<el-table :data="tableData">
<el-table-column prop="name" label="姓名">
<template #default="{ row, column, $index }">
<span class="custom-cell">{{ row.name }}</span>
</template>
</el-table-column>
</el-table>
vue
这种方式直观但不够灵活,列的定义和模板耦合在模板中。
方案二:基于配置对象的渲染函数
const columns = [
{
prop: 'name',
label: '姓名',
cellRenderer: ({ row, column, $index }) => {
return h('span', { class: 'custom-cell' }, row.name)
}
}
]
typescript
灵活但写渲染函数比较繁琐,不够直观。
方案三:统一的 Slot 传参方案
结合两种方式的优点,通过动态组件和函数式 Slot 实现兼容:
<template>
<el-table :data="tableData">
<template v-for="col in columns" :key="col.prop">
<el-table-column :prop="col.prop" :label="col.label">
<template #default="scope">
<!-- 如果列定义了 slotName,使用具名插槽 -->
<slot v-if="col.slotName" :name="col.slotName" v-bind="scope" />
<!-- 否则使用默认渲染 -->
<span v-else>{{ scope.row[col.prop] }}</span>
</template>
</el-table-column>
</template>
</el-table>
</template>
vue
使用方式:
<BasicTable :columns="columns" :table-data="data">
<template #status="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
{{ row.status === 1 ? '启用' : '禁用' }}
</el-tag>
</template>
<template #actions="{ row, $index }">
<el-button size="small" @click="handleEdit(row)">编辑</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">删除</el-button>
</template>
</BasicTable>
vue
const columns = [
{ prop: 'name', label: '姓名' },
{ prop: 'status', label: '状态', slotName: 'status' },
{ prop: 'actions', label: '操作', slotName: 'actions' }
]
typescript
核心设计要点
- 列定义使用配置对象,保持灵活性
- 通过
slotName字段标记需要自定义渲染的列 - 表格组件内部通过
v-bind="scope"透传所有 slot 参数(row、column、$index) - 不需要自定义渲染的列直接显示对应字段值
↑