耀极客论坛

 找回密码
 立即注册
查看: 596|回复: 0

基于el-table封装的可拖拽行列、选择列组件的实现

[复制链接]

193

主题

176

帖子

276

积分

中级会员

Rank: 3Rank: 3

积分
276
发表于 2022-5-9 01:21:31 | 显示全部楼层 |阅读模式
  本文主要介绍了基于el-table封装的可拖拽行列、选择列组件的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
效果

需要环境
  vue
elementUI
拖拽插件Sortable.js
需配置属性

示例
  1. ‹HTable
  2.   :columns="columns"
  3.   :data="list"
  4.   :setColumn="true"
  5.   tableKey="CategoriesList"
  6.   border
  7. >
  8.   // 这里可以放插槽
  9.   ‹template slot="create_time" slot-scope="scope">
  10.     {{ scope.column.label + scope.item.prop }}
  11.   ‹/template>
  12.   ‹template slot="action" slot-scope="scope">
  13.     ‹el-button type="primary" @click="handleEdit(scope.row)" size="small">
  14.       编辑
  15.     ‹/el-button>
  16.     ‹el-button @click="handleDelete(scope.row)" type="danger" size="small">
  17.       删除
  18.     ‹/el-button>
  19.   ‹/template>
  20. ‹/HTable>
  21. import HTable from "@/components/HTable";
  22. export default {
  23.   components: { HTable },
  24.   data() {
  25.     return {
  26.       list: [],
  27.       columns: [
  28.         {
  29.           label: "ID", // 描述
  30.           prop: "_id", // 列的唯一值。 必须要有
  31.           checked: true // 是否展示该列
  32.           ... // 一些el-table-column的属性都可以写在这里
  33.         },
  34.         {
  35.           label: "分类名称",
  36.           prop: "name",
  37.           checked: true
  38.         },
  39.         {
  40.           label: "上级分类",
  41.           prop: "parent.name",
  42.           checked: true
  43.         },
  44.         {
  45.           label: "状态",
  46.           prop: "status",
  47.           width: "100",
  48.           checked: true
  49.         },
  50.         {
  51.           label: "创建时间",
  52.           prop: "create_time",
  53.           slotHeaderName: "create_time", // 自定义表头
  54.           checked: true
  55.         },
  56.         {
  57.           label: "操作",
  58.           prop: "action",
  59.           fixed: "right",
  60.           "min-width": "100",
  61.           slotName: "action", // 自定义单元格插槽
  62.           checked: true,
  63.           disabled: true
  64.         }
  65.       ]
  66.     };
  67.   }
  68. };
复制代码
  有用到的话给我点个赞!附组件代码
  1. ‹template>
  2.   ‹div class="HTable">
  3.     ‹div class="settingBox" v-if="setColumn">
  4.       ‹el-popover
  5.         placement="bottom-end"
  6.         trigger="click"
  7.         popper-class="settingPopper"
  8.       >
  9.         ‹el-checkbox-group
  10.           v-model="selectCol"
  11.           @change="handleChangeSelectColumn"
  12.         >
  13.           ‹el-checkbox
  14.             v-for="item in col"
  15.             :key="item.prop"
  16.             :label="item.prop"
  17.             :disabled="item.disabled"
  18.            
  19.             >{{ item.label }}‹/el-checkbox
  20.           >
  21.         ‹/el-checkbox-group>
  22.         ‹i class="icon el-icon-setting" slot="reference">‹/i>
  23.       ‹/el-popover>
  24.     ‹/div>
  25.     ‹el-table
  26.       v-bind="$attrs"
  27.       :data="tableData"
  28.       v-on="$listeners"
  29.       :key="JSON.stringify(checkedCol)"
  30.     >
  31.       ‹el-table-column
  32.         v-for="(item, index) in checkedCol"
  33.         :key="item.prop"
  34.         v-bind="item"
  35.         :index="index"
  36.         :column-key="item.prop"
  37.       >
  38.         ‹template v-if="item.slotHeaderName" v-slot:header="scope">
  39.           ‹slot :name="item.slotHeaderName" v-bind="scope" :item="item">‹/slot>
  40.         ‹/template>
  41.         ‹template v-if="item.slotName" v-slot:default="scope">
  42.           ‹slot :name="item.slotName" v-bind="scope">‹/slot>
  43.         ‹/template>
  44.       ‹/el-table-column>
  45.     ‹/el-table>
  46.   ‹/div>
  47. ‹/template>
  48. ‹script>
  49. import Sortable from "sortablejs";
  50. export default {
  51.   name: "HTable",
  52.   props: {
  53.     tableKey: String,
  54.     columns: {
  55.       type: Array,
  56.       default() {
  57.         return [];
  58.       }
  59.     },
  60.     data: {
  61.       type: Array,
  62.       default() {
  63.         return [];
  64.       }
  65.     },
  66.     setColumn: {
  67.       type: Boolean,
  68.       default: false
  69.     }
  70.   },
  71.   watch: {
  72.     columns: {
  73.       handler(newVal) {
  74.         let localVal = this.getStorageCol();
  75.         let hotVal = [];
  76.         if (localVal) {
  77.           hotVal = this.dataDiff(newVal, localVal);
  78.         } else {
  79.           hotVal = [...newVal];
  80.         }
  81.         this.col = hotVal.map(
  82.           (item, index) =>
  83.             (item = { ...item, index, checked: item.checked || false })
  84.         );
  85.         this.checkedCol = this.checkedColFun(this.col);
  86.         this.selectCol = this.checkedCol.map(item => (item = item.prop));
  87.       },
  88.       immediate: true
  89.     },
  90.     data: {
  91.       handler(newVal) {
  92.         this.tableData = [...newVal];
  93.       },
  94.       immediate: true
  95.     },
  96.     col: {
  97.       handler(newVal) {
  98.         this.setStorageCol(newVal);
  99.       },
  100.       deep: true,
  101.       immediate: true
  102.     }
  103.   },
  104.   data() {
  105.     return {
  106.       tableData: [],
  107.       col: [],
  108.       checkedCol: [],
  109.       selectCol: []
  110.     };
  111.   },
  112.   mounted() {
  113.     document.body.ondrop = function(event) {
  114.       event.preventDefault();
  115.       event.stopPropagation();
  116.     };
  117.     this.$nextTick(() => {
  118.       this.rowDrop();
  119.       this.columnDrop();
  120.     });
  121.   },
  122.   methods: {
  123.     drap() {
  124.       this.$nextTick(() => {
  125.         this.rowDrop();
  126.         this.columnDrop();
  127.       });
  128.     },
  129.     handleChangeSelectColumn() {
  130.       this.col.forEach(item => {
  131.         if (this.selectCol.includes(item.prop)) {
  132.           item.checked = true;
  133.         } else {
  134.           item.checked = false;
  135.         }
  136.       });
  137.       this.checkedCol = this.checkedColFun(this.col);
  138.       this.drap();
  139.     },
  140.     rowDrop() {
  141.       const tbody = document.querySelector(".el-table__body-wrapper tbody");
  142.       Sortable.create(tbody, {
  143.         onEnd: ({ newIndex, oldIndex }) => {
  144.           [this.tableData[newIndex], this.tableData[oldIndex]] = [
  145.             this.tableData[oldIndex],
  146.             this.tableData[newIndex]
  147.           ];
  148.           this.drap();
  149.           this.$emit("dropRow", {
  150.             drapRow: this.tableData[oldIndex],
  151.             targetRow: this.tableData[newIndex],
  152.             drapRowIndex: oldIndex,
  153.             targetRowIndex: newIndex,
  154.             data: this.tableData
  155.           });
  156.         }
  157.       });
  158.     },
  159.     columnDrop() {
  160.       const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
  161.       Sortable.create(wrapperTr, {
  162.         animation: 180,
  163.         delay: 0,
  164.         onEnd: ({ newIndex, oldIndex }) => {
  165.           const oldItem = this.checkedCol[oldIndex];
  166.           const newItem = this.checkedCol[newIndex];
  167.           [this.col[newItem.index].index, this.col[oldItem.index].index] = [
  168.             oldItem.index,
  169.             newItem.index
  170.           ];
  171.           this.col.sort((a, b) => {
  172.             return a.index - b.index;
  173.           });
  174.           this.checkedCol = this.checkedColFun(this.col);
  175.           this.tableData = this.tableData.slice(0, this.tableData.length);
  176.           this.drap();
  177.           this.$emit("dropCol", {
  178.             colItem: oldItem,
  179.             newIndex: newIndex,
  180.             oldIndex: oldIndex,
  181.             column: this.checkedCol
  182.           });
  183.         }
  184.       });
  185.     },
  186.     checkedColFun(arr) {
  187.       return arr.filter(item => item.checked);
  188.     },
  189.     setStorageCol(data) {
  190.       if (this.tableKey && data && data.length > 0) {
  191.         localStorage.setItem("HTable-" + this.tableKey, JSON.stringify(data));
  192.       }
  193.     },
  194.     getStorageCol() {
  195.       let datajson = localStorage.getItem("HTable-" + this.tableKey);
  196.       return datajson ? JSON.parse(datajson) : "";
  197.     },
  198.     dataDiff(newVal, localVal) {
  199.       let nl = newVal.length;
  200.       let ll = localVal.length;
  201.       if (nl != ll) {
  202.         return newVal;
  203.       } else {
  204.         let np = newVal.map(item => item.prop).sort();
  205.         let lp = localVal.map(item => item.prop).sort();
  206.         if (np.join() != lp.join()) {
  207.           return newVal;
  208.         } else {
  209.           let nnl = [];
  210.           for (let i = 0; i ‹ localVal.length; i++) {
  211.             const item_l = localVal[i];
  212.             for (let j = 0; j ‹ newVal.length; j++) {
  213.               const item_n = newVal[j];
  214.               if (item_l.prop === item_n.prop) {
  215.                 nnl.push({
  216.                   ...item_n,
  217.                   index: item_l.index
  218.                 });
  219.               }
  220.             }
  221.           }
  222.           return nnl;
  223.         }
  224.       }
  225.     }
  226.   }
  227. };
  228. ‹/script>
  229. ‹style lang="less" scoped>
  230. .HTable {
  231.   position: relative;
  232.   .settingBox {
  233.     width: 36px;
  234.     height: 36px;
  235.     border-radius: 2px;
  236.     border: 1px solid #ebeef5;
  237.     border-bottom: 0;
  238.     margin-left: auto;
  239.     position: relative;
  240.     .icon {
  241.       position: absolute;
  242.       top: 0;
  243.       left: 0;
  244.       z-index: 1;
  245.       width: 36px;
  246.       height: 36px;
  247.       text-align: center;
  248.       font-size: 20px;
  249.       line-height: 36px;
  250.       color: #909399;
  251.       cursor: pointer;
  252.     }
  253.   }
  254. }
  255. ‹/style>
  256. ‹style lang="less">
  257. .settingPopper {
  258.   min-width: 100px !important;
  259. }
  260. ‹/style>
复制代码
  到此这篇关于基于el-table封装的可拖拽行列、选择列组件的实现的文章就介绍到这了,更多相关el-table 可拖拽行列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|耀极客论坛 ( 粤ICP备2022052845号-2 )|网站地图

GMT+8, 2022-12-10 02:25 , Processed in 0.064059 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表