基于el-table封裝的可拖拽行列、選擇列組件的實現(xiàn)
效果
需要環(huán)境
需配置屬性
示例
<HTable :columns="columns" :data="list" :setColumn="true" tableKey="CategoriesList" style="width: 100%" 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: "狀態(tài)", prop: "status", width: "100", checked: true }, { label: "創(chuàng)建時間", 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" style="display:block;line-height:2;margin-right:0;" >{{ 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>
到此這篇關(guān)于基于el-table封裝的可拖拽行列、選擇列組件的實現(xiàn)的文章就介紹到這了,更多相關(guān)el-table 可拖拽行列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!?
相關(guān)文章
vue路由跳轉(zhuǎn)攜帶參數(shù)的方式總結(jié)
我們知道在vue中每個頁面都需要在路由中聲明,下面這篇文章主要給大家介紹了關(guān)于vue路由跳轉(zhuǎn)攜帶參數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10ElementUI Tag組件實現(xiàn)多標(biāo)簽生成的方法示例
這篇文章主要介紹了ElementUI Tag組件實現(xiàn)多標(biāo)簽生成的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07vue3.0 CLI - 2.2 - 組件 home.vue 的初步改造
這篇文章主要介紹了vue3.0 CLI - 2.2 - 組件 home.vue 的初步改造,home.vue 組件有了兩個屬性:navs 和 tts 屬性,具體實例代碼大家跟隨小編一起通過本文學(xué)習(xí)吧2018-09-09lottie實現(xiàn)vue自定義loading指令及常用指令封裝詳解
這篇文章主要為大家介紹了lottie實現(xiàn)vue自定義loading指令及常用指令封裝,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09VUE配置proxy代理的開發(fā)測試及生產(chǎn)環(huán)境
這篇文章主要為大家介紹了VUE配置proxy代理的開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08