通过封装el-table的方式,创建我们自己的Mytable组件

做了一个图书管理系统,有兴趣的朋友可以看下:图书管理系统演示

1、好处:

通过封装 el-table 组件,创建我们自己的 Mytable 组件,可以带来以下好处:

  1. 复用代码:封装后的组件可以重复使用,避免了在多个地方编写相同功能的代码,减少了代码的冗余和出错的可能性。
  2. 自定义样式:封装后的组件可以自由控制组件的样式,可以根据需要修改组件的外观和交互效果,提高了组件的可定制性。
  3. 增强可读性:封装后的组件命名更具有描述性,更易于理解,提高了代码的可读性,降低了团队协作的难度。
  4. 便于维护:封装后的组件结构清晰,功能独立,易于测试和调试,降低了维护的难度。
  5. 避免重复造轮子:在多人协作的开发环境中,封装公共组件可以避免重复造轮子,提高了团队的开发效率。
  6. 遵循面向对象编程的原则:封装 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>