翼度科技»论坛 编程开发 JavaScript 查看内容

vue3 实现关于 el-table 表格组件的封装及调用方法

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
一、示例图:



二、组件
  1. <template>
  2.   <div class="sn-table" :class="props.colorType === 1 ? '' : 'bg-scroll'">
  3.     <el-table :data="tableData" :row-class-name="tableRowClassName" height="500" style="width: 100%;"
  4.       :default-sort="[{ prop: '正确率', order: 'descending' },{ prop: '未答题数', order: 'descending' }]"
  5.       :class="props.colorType === 1 ? '' : 'bg-scroll'">
  6.       <el-table-column align="center" :prop="item.keyName"
  7.         :sortable="item.keyName==='正确率'&&props.isExistSelect||item.keyName==='未答题数'&&props.isExistSelect?true:false"
  8.         :label="item.keyName" v-for="item in columns"
  9.         :width="item.width ? item.width + 'px' : ''">
  10.         <template #default="scope">
  11.           <div v-if="item.keyName==='正确率'&&props.isExistSelect" class="tag-list">
  12.             <el-progress :percentage="scope.row[item.keyName]" color="#00B386" :stroke-width="10" :text-inside="false"/>
  13.           </div>
  14.         </template>
  15.       </el-table-column>
  16.     </el-table>
  17.   </div>
  18. </template>
  19. <script lang='ts' setup>
  20. type TProps = {
  21.   tableData: any[]
  22.   columns: any[],
  23.   colorType: number, // 颜色类型
  24.   isExistSelect: boolean // 是否存在筛选项
  25. }
  26. const props = withDefaults(defineProps<TProps>(), {})
  27. const tableRowClassName = ({ rowIndex }: { rowIndex: number }) => {
  28.   if (rowIndex % 2 === 1) {
  29.     return props.colorType === 1 ? 'odd-row' : 'class-odd-row'
  30.   } else {
  31.     return props.colorType === 1 ? 'even-row' : 'class-even-row'
  32.   }
  33. }
  34. </script>
  35. <style lang='scss' scoped>
  36. .bg-scroll {
  37.   border-radius: 10px;
  38.   height: 96%;
  39.   overflow-y: scroll;
  40.   &::-webkit-scrollbar {
  41.     width: 5px;
  42.     height: 0 !important;
  43.   }
  44.   &::-webkit-scrollbar-thumb {
  45.     border-radius: 10px;
  46.     background: #eeeeee;
  47.   }
  48. }
  49. .sn-table {
  50.   padding: 0 10px 0 20px;
  51.   :deep(.el-table) {
  52.     color: #ffffff !important;
  53.     tr {
  54.       td {
  55.         border: none;
  56.         padding: 16px 0;
  57.         font-size: 15px;
  58.       }
  59.     }
  60.     th.el-table__cell {
  61.       background: #141414 !important;
  62.       border: none;
  63.       color: #00B386;
  64.       font-size: 14px;
  65.       font-weight: 400;
  66.     }
  67.     .even-row {
  68.       background-color: #333 !important;
  69.     }
  70.     .odd-row {
  71.       background-color: #141414 !important;
  72.     }
  73.     .class-even-row {
  74.       background-color: #333 !important;
  75.     }
  76.     .class-odd-row {
  77.       background-color: #00B386 !important;
  78.     }
  79.   }
  80.   :deep(.el-scrollbar__wrap--hidden-default) {
  81.     background: #141414 !important;
  82.   }
  83.   :deep(.el-table--enable-row-hover) {
  84.     .el-table__body {
  85.       tr:hover>td.el-table__cell {
  86.         color: #8C8C8C;
  87.         background: #333 !important;
  88.       }
  89.     }
  90.   }
  91.   :deep(.el-table__inner-wrapper) {
  92.     &::before {
  93.       background-color: transparent;
  94.     }
  95.   }
  96.   :deep(.el-table .ascending .sort-caret.ascending){
  97.     border-bottom-color:#00B386 !important;
  98.   }
  99.   :deep(.el-table .descending .sort-caret.descending){
  100.     border-top-color:#00B386 !important;
  101.   }
  102.   .ok-text{
  103.     font-size: 35px;
  104.     font-weight: 300;
  105.   }
  106.   .tag-list{
  107.     width: 100%;
  108.     padding: 2px 0;
  109.     .tag-btn{
  110.       border-radius: 5px;
  111.       border: 1px solid #EF8714;
  112.       color: #EF8714;
  113.       padding: 1px 10px;
  114.       margin-right: 15px;
  115.       &:last-child{
  116.         margin-right: 0;
  117.       }
  118.     }
  119.   }
  120. }
  121. :deep(.el-progress){
  122.   width: 185px;
  123.   margin: 0 auto;
  124. }
  125. :deep(.el-progress__text){
  126.   span{
  127.     font-size: 16px;
  128.   }
  129. }
  130. :deep(.el-progress-bar__outer){
  131.   background: #D9D9D9;
  132. }
  133. </style>
复制代码
三、页面调用
  1. <details-table :tableData="knowInfo" :columns="knowColumns" :isExistSelect="false" :colorType="1"/>
  2. <script setup lang="ts">
  3. import { onMounted, ref } from 'vue'
  4. import CanvasVideo from "@/components/CanvasVideo.vue"
  5. const knowInfo = ref<any[]>([])
  6. const knowColumns = ref<any[]>([])
  7. onMounted(()=>{
  8.     init()
  9. })
  10. //数据处理
  11. const init = () => {
  12.     const datas = ref([
  13.         {studentName:'陈佳颖',correctRate:0,noAnswerCount:13},
  14.         {studentName:'丁靖芸',correctRate:0,noAnswerCount:13},
  15.         {studentName:'谷雨恒',correctRate:0,noAnswerCount:13},
  16.         {studentName:'欧阳江源',correctRate:0,noAnswerCount:13},
  17.         {studentName:'任行宽',correctRate:0,noAnswerCount:13},
  18.         {studentName:'任彦宇',correctRate:0,noAnswerCount:13},
  19.         {studentName:'王骁南',correctRate:0,noAnswerCount:13},
  20.         {studentName:'吴骏扬',correctRate:0,noAnswerCount:13}
  21.     ])
  22.     if (datas && datas.length > 0) {
  23.         datas.forEach((it: any, index:number) => {
  24.             knowInfo.value.push({
  25.                 '行号': index+1,
  26.                 '姓名': it.studentName,
  27.                 '正确率': it.correctRate,
  28.                 '未答题数': it.noAnswerCount
  29.             })
  30.         })
  31.         for (const key in knowInfo.value[0]) {
  32.             knowColumns.value.push({
  33.                 keyName: key,
  34.                 width: key === '行号' ? 140 : null
  35.             })
  36.         }
  37.     }
  38. }
  39. </script>
复制代码
四、其他

(1)自定义标题
  1. <el-table :data="datas" style="width: 100%;">
  2.     <el-table-column label="" prop="name" align="center">
  3.         <template #header>
  4.            姓名
  5.         </template>
  6.     </el-table-column>
  7. </el-table>
复制代码
(2)自定义下标
  1. <el-table :data="datas" style="width: 100%;">
  2.     <el-table-column label="行号" align="center">
  3.         <template #default="{$index}">
  4.             {{$index+1}}
  5.         </template>
  6.     </el-table-column>
  7. </el-table>
复制代码
(3)自定义内容
  1. <el-table :data="datas" style="width: 100%;">
  2.     <el-table-column label="姓名" prop="name" align="center">
  3.         <template #default="scope">
  4.             <div>{{scope.row.name}}s</div>
  5.         </template>
  6.     </el-table-column>
  7. </el-table>
复制代码
(4)添加排序(升序、降序)
  1. <el-table :data="datas" style="width: 100%;"
  2.    :default-sort="[{ prop: 'rank', order: 'descending' },{ prop: 'time', order: 'descending' }]">
  3.     <el-table-column label="排名" prop="rank" sortable align="center"/>
  4.     <el-table-column label="时长" prop="time" sortable align="center"/>
  5. </el-table>
复制代码
(5)多选与单选
1. 单选
  1. <el-table :data="datas" style="width: 100%;"
  2.    row-key="id" ref="multipleTable" highlight-current-row @row-click="rowselect" @selection-change="selectGroupChange">
  3.     <el-table-column type="selection" width="55" />
  4.     <el-table-column label="排名" prop="rank" align="center"/>
  5.     <el-table-column label="时长" prop="time" align="center"/>
  6. </el-table>
  7. <script setup lang="ts">
  8. import { ref } from "vue"
  9. const multipleTable = ref()
  10. const handleList = ref([])
  11. // 设置单选||显示高亮
  12. const rowselect = (row:any) => {
  13.   multipleTable.value.toggleRowSelection(row)
  14. }
  15. // 选择多个单选框,只取最后选中的那一个
  16. const selectGroupChange = (row:any) => {
  17.   if (row.length > 1) {
  18.     multipleTable.value.clearSelection()
  19.     multipleTable.value.toggleRowSelection(row.pop())
  20.     return
  21.   }
  22.   if (row.length == 1) {
  23.     handleList.value = row
  24.   } else {
  25.     handleList.value = []
  26.   }
  27. }
  28. </script>
  29. <style lang='scss' scoped>
  30. // 隐藏表头选择框
  31. :deep(.el-table__header){
  32.   .el-checkbox{
  33.     display: none;
  34.   }
  35. }
  36. </style>
复制代码
2. 多选
  1. <el-table :data="datas" style="width: 100%;"
  2.    row-key="id" @select="handleSelectionChange" @select-all="handleAllChange">
  3.     <el-table-column type="selection" width="55" />
  4.     <el-table-column label="排名" prop="rank" align="center"/>
  5.     <el-table-column label="时长" prop="time" align="center"/>
  6. </el-table>
  7. <script setup lang="ts">
  8. // 选择多个选择框
  9. const handleSelectionChange = (selecteds: any, row: any) => {}
  10. // 全选
  11. const handleAllChange= (row:any) => {}
  12. </script>
复制代码
五、实例(实现树形数据与懒加载)

示例图:通过点击当前节点,调用接口展示下一节点,实现列表的增删改查


1、添加修改组件 EditForm.vue
  1. <template>
  2.   <div>
  3.     <el-form
  4.       ref="menuEditForm"
  5.       :model="form"
  6.       :label-width="formLabelWidth"
  7.       :size="size"
  8.       :rules="rules"
  9.       clearable
  10.     >
  11.       <el-row>
  12.         <el-col :span="12">
  13.           <el-form-item label="父级字典:" prop="parentId">
  14.             <el-cascader ref="myCascader" v-model="form.parentId" :props="{ checkStrictly: true,emitPath:false,expandTrigger:'hover' }" :options="menuTree" :show-all-levels="false" placeholder="请选择父级字典" clearable />
  15.           </el-form-item>
  16.         </el-col>
  17.         <el-col :span="12">
  18.           <el-form-item label="字典名称:" :rules="rules.Required" prop="dictionaryName">
  19.             <el-input
  20.               v-model="form.dictionaryName"
  21.               autocomplete="off"
  22.               :show-word-limit="true"
  23.               placeholder="请输入字典名称"
  24.             />
  25.           </el-form-item>
  26.         </el-col>
  27.       </el-row>
  28.       <el-row v-if="title==='添加字典'">
  29.         <el-col :span="24">
  30.           <el-form-item label="字典编码:" :rules="rules.Required" prop="dictionaryCode">
  31.             <el-input
  32.               v-model="form.dictionaryCode"
  33.               autocomplete="off"
  34.               :show-word-limit="true"
  35.               placeholder="请输入字典编码"
  36.             />
  37.           </el-form-item>
  38.         </el-col>
  39.       </el-row>
  40.       <el-form-item
  41.         label="备注:"
  42.         prop="remark"
  43.       >
  44.         <el-input
  45.           v-model="form.remark"
  46.           type="textarea"
  47.           maxlength="200"
  48.           :show-word-limit="true"
  49.           autocomplete="off"
  50.         />
  51.       </el-form-item>
  52.     </el-form>
  53.   </div>
  54. </template>
  55. <script>
  56. import { getChildrens, getDictionaryInfo, EditDictionary } from '@/api/dictionary'
  57. import rules from '@/utils/rules'
  58. export default {
  59.   props: {
  60.     id: {
  61.       type: Number,
  62.       default: 0
  63.     },
  64.     title: {
  65.       type: String,
  66.       default: ''
  67.     }
  68.   },
  69.   data() {
  70.     return {
  71.       menuTree: [], // 字典树
  72.       rules: rules,
  73.       formLabelWidth: '120px',
  74.       size: 'small',
  75.       loading: false,
  76.       form: {
  77.         id: this.id,
  78.         parentId: 0,
  79.         parentDictionaryName: '',
  80.         dictionaryCode: '',
  81.         dictionaryName: '',
  82.         remark: '',
  83.         deleteState: true
  84.       }
  85.     }
  86.   },
  87.   created() {
  88.     this.fetchInitData()
  89.   },
  90.   methods: {
  91.     handlePagedCallback() {
  92.       this.$emit('handlePagedCallback')
  93.     },
  94.     handleSubmitForm() {
  95.       this.$refs['menuEditForm'].validate((valid) => {
  96.         if (valid) {
  97.           this.loading = true
  98.           EditDictionary(this.form).then((res) => {
  99.             this.loading = false
  100.             if (res.code === 200) {
  101.               if (res.data) {
  102.                 this.$message.success('操作成功')
  103.                 this.handlePagedCallback()
  104.               } else {
  105.                 this.$message.error('操作失败')
  106.               }
  107.             } else {
  108.               this.$message.error(res.message)
  109.             }
  110.           })
  111.         }
  112.       })
  113.     },
  114.     handleResetForm() {
  115.       if (this.$refs['menuEditForm']) {
  116.         this.$refs['menuEditForm'].resetFields()
  117.       }
  118.     },
  119.     fetchInitData() {
  120.       getChildrens().then((res) => {
  121.         if (res.code === 200) {
  122.           this.menuTree = JSON.parse(JSON.stringify(res.data).replace(/id/g, 'value').replace(/dictionaryName/g, 'label'))
  123.           this.fetchFormData()
  124.         }
  125.       })
  126.     },
  127.     fetchFormData() {
  128.       this.handleResetForm()
  129.       if (this.id !== 0) {
  130.         const id = { Id: this.id }
  131.         getDictionaryInfo(id).then((res) => {
  132.           if (res.code === 200) {
  133.             this.form = Object.assign(this.form, res.data)
  134.           }
  135.         })
  136.       }
  137.     }
  138.   }
  139. }
  140. </script>
复制代码
2、主页面 index.vue
  1. <template>
  2.   <div class="app-container">
  3.     <div class="search-container">
  4.       <!-- 搜索项目 -->
  5.       <el-form :inline="true" :model="search" size="small">
  6.         <el-form-item>
  7.           <el-input v-model="search.keyword" placeholder="字典名称" />
  8.         </el-form-item>
  9.         <el-form-item>
  10.           <el-button
  11.             v-rolebtn="'BTN-ZDGL-查询'"
  12.             type="primary"
  13.             icon="el-icon-search"
  14.             @click="handleReloadPaged"
  15.           >查询</el-button>
  16.         </el-form-item>
  17.       </el-form>
  18.     </div>
  19.     <div class="toolbar-container">
  20.       <!-- 按钮组 -->
  21.       <el-button
  22.         v-rolebtn="'BTN-ZDGL-新增字典'"
  23.         type="success"
  24.         size="small"
  25.         plain
  26.         @click="AddDialog"
  27.       >新增</el-button>
  28.       <el-button
  29.         v-rolebtn="'BTN-ZDGL-编辑字典'"
  30.         type="primary"
  31.         size="small"
  32.         plain
  33.         @click="EditDialog"
  34.       >修改</el-button>
  35.       <el-button
  36.         v-rolebtn="'BTN-ZDGL-删除字典'"
  37.         type="danger"
  38.         size="small"
  39.         plain
  40.         @click="handleDelete"
  41.       >删除</el-button>
  42.     </div>
  43.     <el-table
  44.       ref="myTable"
  45.       :data="table.data"
  46.       :border="table.border"
  47.       style="width: 100%"
  48.       empty-text="暂无数据"
  49.       row-key="id"
  50.       lazy
  51.       :load="lazyload"
  52.       :default-expand-all="false"
  53.       :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  54.       @selection-change="handleSelectionChange"
  55.     >
  56.       <el-table-column type="selection" width="60" />
  57.       <el-table-column prop="dictionaryName" label="字典名称" />
  58.       <el-table-column prop="dictionaryCode" label="字典编码" />
  59.       <el-table-column prop="parentDictionaryName" label="父级字典名称" />
  60.       <el-table-column prop="createTime" label="创建时间" />
  61.       <el-table-column prop="remark" label="备注" />
  62.     </el-table>
  63.     <Pagination
  64.       :total="pagination.total"
  65.       :current="pagination.index"
  66.       :page-size="pagination.size"
  67.       @handlePaginationChange="handlePaginationChange"
  68.       @handleSizeChange="handlePaginationChange"
  69.     />
  70.     <div class="dialog-container">
  71.       <el-dialog
  72.         v-if="dialog.edit.visible"
  73.         ref="menuEditDialog"
  74.         :title="dialog.edit.title"
  75.         :visible.sync="dialog.edit.visible"
  76.         :width="dialog.edit.width"
  77.         :close-on-click-modal="dialog.close"
  78.         :close-on-press-escape="dialog.close"
  79.       >
  80.         <EditForm
  81.           :id="dialog.edit.id"
  82.           ref="Submit"
  83.           :title="dialog.edit.title"
  84.           @handlePagedCallback="handleEditCallback"
  85.         />
  86.         <span slot="footer" class="dialog-footer">
  87.           <el-button @click="dialog.edit.visible = false">取 消</el-button>
  88.           <el-button type="primary" @click="Submit">确 定</el-button>
  89.         </span>
  90.       </el-dialog>
  91.     </div>
  92.   </div>
  93. </template>
  94. <script>
  95. import Pagination from '@/components/Pagination'
  96. import EditForm from './EditForm'
  97. import { getDictionaryNext, getDictionaryRoute, DeleteDictionaryRoute } from '@/api/dictionary'
  98. export default {
  99.   components: { Pagination, EditForm },
  100.   data() {
  101.     return {
  102.       search: {
  103.         keyword: ''
  104.       },
  105.       searchId: 0,
  106.       // 表格数据
  107.       table: {
  108.         data: [],
  109.         selectRows: [],
  110.         border: false
  111.       },
  112.       currChildren: [],
  113.       // 分页数据
  114.       pagination: {
  115.         index: 1,
  116.         size: 20,
  117.         total: 0
  118.       },
  119.       // 弹出层
  120.       dialog: {
  121.         close: false, // 是否关闭
  122.         edit: {
  123.           id: 0,
  124.           title: '修改字典', // 弹出层title
  125.           visible: false, // 弹出层是否显示
  126.           width: '800px' // 弹出层宽度
  127.         }
  128.       },
  129.       layzNode: null,
  130.       layztreeNode: null,
  131.       layzresolve: null
  132.     }
  133.   },
  134.   created() {
  135.     this.getDictionaryList()
  136.   },
  137.   methods: {
  138.     lazyload(tree, treeNode, resolve) {
  139.       if (tree) {
  140.         var data = {
  141.           Id: tree.id
  142.         }
  143.         getDictionaryNext(data).then((res) => {
  144.           if (res.code === 200) {
  145.             this.layzNode = tree
  146.             this.layztreeNode = treeNode
  147.             this.layzresolve = resolve
  148.             resolve(res.data)
  149.           }
  150.         })
  151.       }
  152.     },
  153.     Submit() {
  154.       this.$refs.Submit.handleSubmitForm()
  155.     },
  156.     // 勾选
  157.     handleSelectionChange(selection) {
  158.       this.table.selectRows = selection
  159.     },
  160.     // 新增
  161.     AddDialog() {
  162.       this.dialog.edit.id = 0
  163.       this.dialog.edit.title = '添加字典'
  164.       this.dialog.edit.visible = true
  165.     },
  166.     // 修改
  167.     EditDialog() {
  168.       if (this.table.selectRows.length !== 1) {
  169.         this.$message.warning('请选择要修改的字典')
  170.       } else {
  171.         this.dialog.edit.id = this.table.selectRows[0].id
  172.         this.dialog.edit.title = '修改字典'
  173.         this.dialog.edit.visible = true
  174.       }
  175.     },
  176.     // 修改成功回调
  177.     handleEditCallback() {
  178.       this.dialog.edit.visible = false
  179.       this.dialog.edit.id = 0
  180.       this.$nextTick(() => {
  181.         this.$set(this.$refs.myTable.store.states.lazyTreeNodeMap, this.layzNode.id, [])
  182.         this.lazyload(this.layzNode, this.layztreeNode, this.layzresolve)
  183.         this.getDictionaryList()
  184.       })
  185.     },
  186.     // 删除
  187.     handleDelete() {
  188.       if (this.table.selectRows.length === 0) {
  189.         this.$message.warning('未勾选记录')
  190.         return
  191.       }
  192.       const ids = []
  193.       this.table.selectRows.forEach((it) => {
  194.         ids.push(it.id)
  195.       })
  196.       this.$confirm('此操作将永久删除勾选记录, 是否继续?').then(() => {
  197.         DeleteDictionaryRoute(ids).then((res) => {
  198.           if (res.code === 200) {
  199.             if (res.data) {
  200.               this.$nextTick(() => {
  201.                 this.getDictionaryList()
  202.                 this.$set(this.$refs.myTable.store.states.lazyTreeNodeMap, this.layzNode.id, [])
  203.                 this.lazyload(this.layzNode, this.layztreeNode, this.layzresolve)
  204.               })
  205.               this.$message.success('操作成功')
  206.             } else {
  207.               this.$message.error('操作失败')
  208.             }
  209.           } else {
  210.             this.$message.error(res.message)
  211.           }
  212.         })
  213.       })
  214.     },
  215.     // 列表接口
  216.     getDictionaryList() {
  217.       var data = {
  218.         searchName: this.search.keyword,
  219.         searchId: this.searchId,
  220.         pageIndex: this.pagination.index,
  221.         pageSize: this.pagination.size
  222.       }
  223.       getDictionaryRoute(data).then((res) => {
  224.         if (res.code === 200) {
  225.           this.pagination.total = res.data.total
  226.           this.table.data = res.data.data
  227.         }
  228.       })
  229.     },
  230.     // 重载表格
  231.     handleReloadPaged() {
  232.       this.pagination.index = 1
  233.       this.getDictionaryList()
  234.     },
  235.     // 分页变更
  236.     handlePaginationChange(data) {
  237.       this.pagination.index = data.current
  238.       this.pagination.size = data.pageSize
  239.       this.getDictionaryList()
  240.     }
  241.   }
  242. }
  243. </script>
复制代码
      希望我的愚见能够帮助你哦~,若有不足之处,还望指出,你们有更好的解决方法,欢迎大家在评论区下方留言支持,大家一起相互学习参考呀~
到此这篇关于vue3 实现关于 el-table 表格组件的封装以及调用的文章就介绍到这了,更多相关vue3 el-table 表格组件封装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/323398vbf.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具