通过封装el-table的方式,创建我们自己的Mytable组件
做了一个图书管理系统,有兴趣的朋友可以看下:图书管理系统演示
1、好处:
通过封装 el-table
组件,创建我们自己的 Mytable
组件,可以带来以下好处:
- 复用代码:封装后的组件可以重复使用,避免了在多个地方编写相同功能的代码,减少了代码的冗余和出错的可能性。
- 自定义样式:封装后的组件可以自由控制组件的样式,可以根据需要修改组件的外观和交互效果,提高了组件的可定制性。
- 增强可读性:封装后的组件命名更具有描述性,更易于理解,提高了代码的可读性,降低了团队协作的难度。
- 便于维护:封装后的组件结构清晰,功能独立,易于测试和调试,降低了维护的难度。
- 避免重复造轮子:在多人协作的开发环境中,封装公共组件可以避免重复造轮子,提高了团队的开发效率。
- 遵循面向对象编程的原则:封装
el-table
组件为Mytable
组件,符合面向对象编程的原则,提高了代码的灵活性和可扩展性。
2、MyTable.vue
MyTable组件用到了模板、属性、计算属性和方法
- 模板:包含el-table和el-table-column组件,用于呈现表格和表格列。
- 属性:通过props属性,接收父组件传递过来的columns和data,覆盖子组件包括表格列、表格数据、表格高度、表格最大高度、是否显示条纹、是否显示边框、是否显示表头、是否高亮当前行和行的类名等属性,达到配置的目的。
- 计算属性:用于在表格数据中添加序号列。
- 方法:用于处理行点击和按钮点击事件,以及获取标签。
<template>
<div>
<!-- 渲染表格 -->
<el-table :data="tableData" :height="height" :max-height="maxHeight" :stripe="stripe" :border="border"
:show-header="showHeader" :highlight-current-row="highlightCurrentRow" :row-class-name="rowClassName"
@row-click="handleRowClick">
<!-- 渲染表格列 -->
<el-table-column v-for="(column, index) in columns" :key="index" :prop="column.prop" :label="column.label"
:width="column.width" :min-width="column.minWidth" :fixed="column.fixed"
:sortable="column.sortable" :resizable="column.resizable" :formatter="column.formatter"
:show-overflow-tooltip="column.showOverflowTooltip">
<!-- 渲染插槽列 -->
<template v-if="column.type === 'slot' && column.slotName === 'image'" v-slot="scope">
<img :src="scope.row.image" width="100px" height="170px" alt="Image">
</template>
<template v-else-if="column.type === 'slot' && column.slotName === 'tag'" v-slot="scope">
<el-tag v-if="getTag(scope.row[column.prop], column.tags)"
:type="getTag(scope.row[column.prop], column.tags).tagType"
:key="getTag(scope.row[column.prop], column.tags).tagValue">
{{ getTag(scope.row[column.prop], column.tags).tagLabel }}
</el-tag>
</template>
<template v-else-if="column.type === 'button'" v-slot="scope">
<template v-for="(button, index) in column.buttons">
<!-- 渲染按钮 -->
<el-button v-has="button.btnPermission" :key="index" :type="button.type"
@click="handleButtonClick(scope.row, button.code)">{{ button.text }}
</el-button>
</template>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'MyTable',
props: {
// 表格列
columns: {
type: Array,
default: () => []
},
// 表格数据
data: {
type: Array,
default: () => []
},
// 表格高度
height: {
type: String,
default: '600'
},
// 表格最大高度
maxHeight: {
type: String,
default: '600'
},
// 是否显示条纹
stripe: {
type: Boolean,
default: true
},
// 是否显示边框
border: {
type: Boolean,
default: true
},
// 是否显示表头
showHeader: {
type: Boolean,
default: true
},
// 是否高亮当前行
highlightCurrentRow: {
type: Boolean,
default: true
},
// 行的类名
rowClassName: {
type: Function,
default: () => ''
}
},
computed: {
// 添加序号列
tableData() {
return this.data.map((item, index) => {
return {
...item,
index: index + 1
}
})
}
},
methods: {
// 处理行点击事件
handleRowClick(row, column, event) {
this.$emit('row-click', row, column, event)
},
// 处理按钮点击事件
handleButtonClick(row, column) {
this.$emit('button-click', row, column)
},
// 获取标签
getTag(value, tags) {
return tags.find(tag => tag.tagValue === value);
}
}
}
</script>
3、调用MyTable组件
包含了一个 ElementUI 的 el-card 组件和自定义的 my-table 和 my-form 组件。my-table 组件通过传递 props 实现了对表格数据和列的渲染,同时支持行点击和按钮点击事件。my-form 组件实现了图书信息的添加和编辑功能。整个组件的数据和方法都被定义在 Vue 实例中,可以通过 Vue 的生命周期函数 mounted 来调用后端 API 获取数据。
<template xmlns:el="http://www.w3.org/1999/html">
<div>
<!-- el-card 是 ElementUI 的组件,用于包裹整个表格 -->
<el-card class="box-card">
<!-- MyTable 是自定义的表格组件,通过传递 props 实现数据的渲染 -->
<my-table :columns="columns" :data="tableData" @row-click="handleRowClick"
@button-click="handleButtonClick"></my-table>
</el-card>
</div>
</template>
<script>
import {getBooks,addBook,getFileUploadPath} from "@/utils/http";
import MyTable from "@/components/MyTable";
export default {
name: "User", // 组件名称
components: {
MyTable // 引入自定义组件 MyTable 和 MyForm
},
data() {
return {
tableData: [], // 表格数据
columns: [ // 图书表格列
{label: 'id', prop: 'id', width: 50}, // 列名为 id,列宽为 50
{label: '缩略图', prop: 'image', width: 130, type: 'slot', slotName: 'image'}, // 列名为缩略图,列宽为 130,使用插槽渲染
{label: '书籍名称', prop: 'title', width: 130}, // 列名为书籍名称,列宽为 130
{label: '书籍作者', prop: 'author', width: 80}, // 列名为书籍作者,列宽为 80
{label: '上市时间', prop: 'publishDate', width: 100}, // 列名为上市时间,列宽为 100
{label: '书籍描述', prop: 'description'}, // 列名为书籍描述
{
label: '书籍状态', prop: 'status', width: 100, type: 'slot', slotName: 'tag' // 列名为书籍状态,使用插槽渲染
, tags: [ // 状态标签
{tagValue: '0', tagLabel: '未借阅', tagType: "warning"},
{tagValue: '1', tagLabel: '已借阅', tagType: "success"},
]
},
{
label: '操作', // 操作列
type: 'button', // 操作类型为按钮
width: 200, // 列宽为 200
buttons: [ // 操作按钮
{
text: '修改',
type: 'primary',
code: 'edit',
btnPermission: '/book/update', // 按钮权限
},
{
text: '删除',
type: 'danger',
code: 'del',
btnPermission: '/book/delete', // 按钮权限
}
]
}
],
},
methods: {
handleRowClick(row, column, event) {
console.log('Roles row clicked:', row)
},
},
mounted() {
getBooks().then(res => {
if (res) {
this.tableData = res;
}
})
}
}
</script>
<style scoped>
</style>