本篇文章为大家展示了如何进行基于el-table封装的可拖拽行列、选择列组件的实现,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
效果
需要环境
vue
elementUI
拖拽插件Sortable.js
需配置属性
示例
<HTable :columns="columns" :data="list" :setColumn="true" tableKey="CategoriesList" border> // 这里可以放插槽 <template slot="create_time" slot-scope="scope"> {{ scope.column.label + scope.item.prop }} </template> <template slot="action" slot-scope="scope"> <el-button type="primary" @click="handleEdit(scope.row)" size="small"> 编辑 </el-button> <el-button @click="handleDelete(scope.row)" type="danger" size="small"> 删除 </el-button> </template></HTable>import HTable from "@/components/HTable";export default { components: { HTable }, data() { return { list: [], columns: [ { label: "ID", // 描述 prop: "_id", // 列的唯一值。 必须要有 checked: true // 是否展示该列 ... // 一些el-table-column的属性都可以写在这里 }, { label: "分类名称", prop: "name", checked: true }, { label: "上级分类", prop: "parent.name", checked: true }, { label: "状态", prop: "status", width: "100", checked: true }, { label: "创建时间", prop: "create_time", slotHeaderName: "create_time", // 自定义表头 checked: true }, { label: "操作", prop: "action", fixed: "right", "min-width": "100", slotName: "action", // 自定义单元格插槽 checked: true, disabled: true } ] }; }};
有用到的话给我点个赞!附组件代码
<template> <div class="HTable"> <div class="settingBox" v-if="setColumn"> <el-popover placement="bottom-end" trigger="click" popper-class="settingPopper" > <el-checkbox-group v-model="selectCol" @change="handleChangeSelectColumn" > <el-checkbox v-for="item in col" :key="item.prop" :label="item.prop" :disabled="item.disabled" >{{ item.label }}</el-checkbox > </el-checkbox-group> <i class="icon el-icon-setting" slot="reference"></i> </el-popover> </div> <el-table v-bind="$attrs" :data="tableData" v-on="$listeners" :key="JSON.stringify(checkedCol)" > <el-table-column v-for="(item, index) in checkedCol" :key="item.prop" v-bind="item" :index="index" :column-key="item.prop" > <template v-if="item.slotHeaderName" v-slot:header="scope"> <slot :name="item.slotHeaderName" v-bind="scope" :item="item"></slot> </template> <template v-if="item.slotName" v-slot:default="scope"> <slot :name="item.slotName" v-bind="scope"></slot> </template> </el-table-column> </el-table> </div></template><script>import Sortable from "sortablejs";export default { name: "HTable", props: { tableKey: String, columns: { type: Array, default() { return []; } }, data: { type: Array, default() { return []; } }, setColumn: { type: Boolean, default: false } }, watch: { columns: { handler(newVal) { let localVal = this.getStorageCol(); let hotVal = []; if (localVal) { hotVal = this.dataDiff(newVal, localVal); } else { hotVal = [...newVal]; } this.col = hotVal.map( (item, index) => (item = { ...item, index, checked: item.checked || false }) ); this.checkedCol = this.checkedColFun(this.col); this.selectCol = this.checkedCol.map(item => (item = item.prop)); }, immediate: true }, data: { handler(newVal) { this.tableData = [...newVal]; }, immediate: true }, col: { handler(newVal) { this.setStorageCol(newVal); }, deep: true, immediate: true } }, data() { return { tableData: [], col: [], checkedCol: [], selectCol: [] }; }, mounted() { document.body.ondrop = function(event) { event.preventDefault(); event.stopPropagation(); }; this.$nextTick(() => { this.rowDrop(); this.columnDrop(); }); }, methods: { drap() { this.$nextTick(() => { this.rowDrop(); this.columnDrop(); }); }, handleChangeSelectColumn() { this.col.forEach(item => { if (this.selectCol.includes(item.prop)) { item.checked = true; } else { item.checked = false; } }); this.checkedCol = this.checkedColFun(this.col); this.drap(); }, rowDrop() { const tbody = document.querySelector(".el-table__body-wrapper tbody"); Sortable.create(tbody, { onEnd: ({ newIndex, oldIndex }) => { [this.tableData[newIndex], this.tableData[oldIndex]] = [ this.tableData[oldIndex], this.tableData[newIndex] ]; this.drap(); this.$emit("dropRow", { drapRow: this.tableData[oldIndex], targetRow: this.tableData[newIndex], drapRowIndex: oldIndex, targetRowIndex: newIndex, data: this.tableData }); } }); }, columnDrop() { const wrapperTr = document.querySelector(".el-table__header-wrapper tr"); Sortable.create(wrapperTr, { animation: 180, delay: 0, onEnd: ({ newIndex, oldIndex }) => { const oldItem = this.checkedCol[oldIndex]; const newItem = this.checkedCol[newIndex]; [this.col[newItem.index].index, this.col[oldItem.index].index] = [ oldItem.index, newItem.index ]; this.col.sort((a, b) => { return a.index - b.index; }); this.checkedCol = this.checkedColFun(this.col); this.tableData = this.tableData.slice(0, this.tableData.length); this.drap(); this.$emit("dropCol", { colItem: oldItem, newIndex: newIndex, oldIndex: oldIndex, column: this.checkedCol }); } }); }, checkedColFun(arr) { return arr.filter(item => item.checked); }, setStorageCol(data) { if (this.tableKey && data && data.length > 0) { localStorage.setItem("HTable-" + this.tableKey, JSON.stringify(data)); } }, getStorageCol() { let datajson = localStorage.getItem("HTable-" + this.tableKey); return datajson ? JSON.parse(datajson) : ""; }, dataDiff(newVal, localVal) { let nl = newVal.length; let ll = localVal.length; if (nl != ll) { return newVal; } else { let np = newVal.map(item => item.prop).sort(); let lp = localVal.map(item => item.prop).sort(); if (np.join() != lp.join()) { return newVal; } else { let nnl = []; for (let i = 0; i < localVal.length; i++) { const item_l = localVal[i]; for (let j = 0; j < newVal.length; j++) { const item_n = newVal[j]; if (item_l.prop === item_n.prop) { nnl.push({ ...item_n, index: item_l.index }); } } } return nnl; } } } }};</script><style lang="less" scoped>.HTable { position: relative; .settingBox { width: 36px; height: 36px; border-radius: 2px; border: 1px solid #ebeef5; border-bottom: 0; margin-left: auto; position: relative; .icon { position: absolute; top: 0; left: 0; z-index: 1; width: 36px; height: 36px; text-align: center; font-size: 20px; line-height: 36px; color: #909399; cursor: pointer; } }}</style><style lang="less">.settingPopper { min-width: 100px !important;}</style>
上述内容就是如何进行基于el-table封装的可拖拽行列、选择列组件的实现,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。