实现支持作用域插槽的通用数据表格组件

📅 2026/6/25 16:21:59
实现支持作用域插槽的通用数据表格组件
实现支持作用域插槽的通用数据表格组件在 Vue 中作用域插槽Scoped Slots是让父组件自定义子组件内部渲染的利器。下面实现一个DataTable组件它接收data行数据和columns列配置数组并在每个td中提供插槽让父组件按列自定义单元格内容。1. 子组件DataTable.vueVue 3 script setup核心逻辑遍历columns为每一列生成th。遍历data生成tr再遍历columns生成td。每个td内优先检查父组件是否传递了对应列的具名插槽以列字段field命名若存在则使用插槽并传递row、column、index等作用域数据否则显示默认的row[field]值。template table classdata-table thead tr th v-forcol in columns :keycol.field {{ col.title || col.field }} /th /tr /thead tbody tr v-for(row, rowIndex) in data :keyrowIndex td v-forcol in columns :keycol.field !-- 作用域插槽使用列字段作为插槽名同时提供后备内容 -- slot :namecol.field :rowrow :columncol :indexrowIndex !-- 默认显示 -- {{ row[col.field] }} /slot /td /tr /tbody /table /template script setup defineProps({ data: { type: Array, required: true, default: () [] }, columns: { type: Array, required: true, // 列对象格式{ field: name, title: 姓名 } default: () [] } }) /script style scoped .data-table { border-collapse: collapse; width: 100%; } .data-table th, .data-table td { border: 1px solid #ddd; padding: 8px 12px; text-align: left; } .data-table th { background-color: #f5f5f5; } /style2. 父组件使用示例父组件通过v-slot指令或#缩写为指定列提供自定义渲染。作用域数据包括row当前行的完整数据对象column当前列配置index行索引template div DataTable :datatableData :columnscolumns !-- 自定义 status 列显示不同颜色的标签 -- template #status{ row } span :classrow.status active ? tag-active : tag-inactive {{ row.status }} /span /template !-- 自定义 actions 列放置操作按钮 -- template #actions{ row, index } button clickeditRow(row, index)编辑/button button clickdeleteRow(index)删除/button /template !-- 其他未自定义的列如 name, age会自动使用默认渲染 -- /DataTable /div /template script setup import { ref } from vue import DataTable from ./DataTable.vue const columns [ { field: name, title: 姓名 }, { field: age, title: 年龄 }, { field: status, title: 状态 }, { field: actions, title: 操作 } ] const tableData ref([ { name: 张三, age: 28, status: active }, { name: 李四, age: 34, status: inactive }, { name: 王五, age: 22, status: active } ]) const editRow (row, index) { alert(编辑第 ${index 1} 行${row.name}) } const deleteRow (index) { tableData.value.splice(index, 1) } /script style scoped .tag-active { color: green; font-weight: bold; } .tag-inactive { color: red; } /style