Vue.js中el-table表格自定義列控制與拖拽
背景
昨天客戶:提了一個(gè)需求,你們這個(gè)表格的數(shù)據(jù)太亂不是我們重點(diǎn)關(guān)注的,然后列出了一些屬性值A(chǔ),B,C,D。。。這些必須展示。

前端仔:簡(jiǎn)單,30s給你安排上。
今天客戶:你們這個(gè)表格的列字段不能拖動(dòng)呀,我們覺(jué)得這個(gè)幾個(gè)字段才是我們重點(diǎn)關(guān)注的,我要放到前面。。
前端仔:無(wú)語(yǔ),行給你安排。
這些無(wú)聊的需求不改又不行,但是自己又不想被他們拖著天天伺候,直接給他們自己可以配置,想咋弄就咋弄。
需求與實(shí)現(xiàn)分析(重點(diǎn))
面對(duì)客戶的這些需求,總結(jié)起來(lái)也就是2個(gè)功能點(diǎn),一是表格的列可以自由拖拽,二表格可以展示的列數(shù)據(jù)可以進(jìn)行自定義控制。考慮到組件可能會(huì)在很多地方使用,所以使用父子傳值的模式來(lái)進(jìn)行數(shù)據(jù)傳輸。
功能實(shí)現(xiàn)
自由拖拽:偷個(gè)懶直接應(yīng)用別人封裝好的sortable.js。地址:www.sortablejs.com/
引入
npm install sortablejs
使用
import Sortable from "sortablejs";
**列控制:**這里考慮使用leement的多選框組el-check-group,我們先自定義一部分默認(rèn)顯示的數(shù)據(jù),還有一部分由客戶自己勾選設(shè)置,這樣既可以避免表格內(nèi)容過(guò)多,導(dǎo)致出現(xiàn)橫向滾動(dòng)條的丑陋,也為客戶提供了選擇性。
上組件代碼
<template>
<div class="myWrap">
<div class="colum-set">
<el-popover width="150" placement="bottom-end" trigger="click">
<div>
<el-checkbox-group v-model="childCheckedItems" @change="handleCheckedColumChange">
<el-checkbox v-for="item in tableHeader" :label="item.label" :key="item.label"></el-checkbox>
</el-checkbox-group>
</div>
<el-button slot="reference" size="mini" icon="el-icon-setting">{{ $t('common.column_set') }}</el-button>
</el-popover>
</div>
<el-table :data="tableBody" @selection-change="handleSelectionChange" border row-key="id" :header-cell-style="{
height: '48px',
background: '#DFEBF9',
color: '#606266',
fontWeight: 'bold',
fontSize: '14px',
}">
<!-- 勾選框列 -->
<el-table-column type="selection" width="48" fixed v-if="needCheckBox"></el-table-column>
<!-- 表頭列 -->
<el-table-column v-for="(item, index) in checkedHeader" :key="index" :prop="item.prop" :label="item.label"
width="auto" show-overflow-tooltip>
</el-table-column>
<!-- 表格操作 -->
<el-table-column :width="tableOperate.width" :label="tableOperate.label" fixed="right" v-if="tableOperate.show">
<template slot-scope="scope">
<slot name="tablerow" :row="scope.row"></slot>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
// 引入sortablejs插件,拖拽主要靠的是這個(gè)插件
import Sortable from "sortablejs";
export default {
props: {
tableBody: {
required: true,
type: Array
},
tableHeader: {
type: Array,
required: true
},
needCheckBox: {
required: true,
type: Boolean
},
tableOperate:{
required:true,
type:Object
}
},
data() {
return {
checkedHeader: [],
childCheckedItems: []
};
},
watch: {
'$store.state.common.lang': function (val) {
window.location.reload()
},
tableHeader: {
handler(newVal, oldVal) {
console.log(newVal)
this.checkedHeader = newVal.filter(item => item.show == true)
this.childCheckedItems = this.checkedHeader.map(item => {
return item.label
})
},
immediate: true,
deep: true
}
},
mounted() {
// 列的拖拽初始化
this.columnDropInit();
},
methods: {
//列拖拽
columnDropInit() {
// 第一步,獲取列容器
const wrapperColumn = document.querySelector(
".el-table__header-wrapper tr"
);
// 第二步,給列容器指定對(duì)應(yīng)拖拽規(guī)則
this.sortable = Sortable.create(wrapperColumn, {
animation: 200,
delay: 0,
onEnd: (event) => {
console.log(
"根據(jù)舊索引和新索引去更新,其實(shí)就是交換位置",
event.oldIndex,
event.newIndex
);
// 接下來(lái)做索引的交換
let tempHableHeader = [...this.checkedHeader]; // 先存一份臨時(shí)變量表頭數(shù)據(jù)
let temp; // 臨時(shí)變量用于交換
// 這里預(yù)留一個(gè)變量,因?yàn)楸眍^前加了表格多選,且固定。那么得-1,如果還有2列,則-2,以此類(lèi)推
temp = tempHableHeader[event.oldIndex - this.control_index];
tempHableHeader[event.oldIndex - this.control_index] =
tempHableHeader[event.newIndex - this.control_index];
tempHableHeader[event.newIndex - this.control_index] = temp;
// 這里一定要先把表頭數(shù)據(jù)清空,然后再下一輪中去賦值,bug處理
this.checkedHeader = []
this.$nextTick(() => {
this.checkedHeader = tempHableHeader
this.childCheckedItems = this.checkedHeader.map(item => {
return item.label
})
})
},
});
},
handleCheckedColumChange(value) {
this.$emit('changeCheckedColum', value)
},
handleSelectionChange(value){
console.log(value)
}
},
};
</script>
<style lang='stylus' scoped>
.myWrap {
width: 100%;
height: 100%;
box-sizing: border-box;
.colum-set{
float: right;
}
/deep/ .el-table {
.el-table__header-wrapper {
tr {
th {
cursor: move;
}
}
}
}
}
.check-colum-div{
width: 150px;
display: flex;
flex-direction: column;
}
</style>父組件核心代碼
<template>
<MyTable :tableBody="matlist" :tableHeader="tableHeader" :needCheckBox="true" :tableOperate="tableOperate"
@changeCheckedColum="changeCheckedColum" >
<template v-slot:tablerow="scope">
<el-button type="primary" size="small" @click="editRow(scope.row)">
編輯
</el-button>
</template>
</MyTable>
</template>
<script>
tableHeader: [
{ label: this.$t('storage.shelf_id'), prop: 'shelf_id', show: true },
{ label: this.$t('storage.save_id'), prop: 'save_id', show: false },
{ label: this.$t('storage.label_code'), prop: 'label_code', show: true },
{ label: this.$t('storage.part_num'), prop: 'part_num', show: true },
{ label: this.$t('storage.lot_code'), prop: 'lot_code', show: true },
{ label: this.$t('storage.quantity'), prop: 'quantity', show: true },
{ label: this.$t('storage.description'), prop: 'description', show: true },
{ label: this.$t('storage.supplier_name'), prop: 'supplier_name', show: true },
{ label: this.$t('storage.mfg_date'), prop: 'mfg_date', show: true },
{ label: this.$t('storage.in_time'), prop: 'in_time', show: true },
{ label: this.$t('storage.position'), prop: 'position_info', show: true },
{ label: this.$t('storage.category_name'), prop: 'category_name', show: false },
{ label: this.$t('storage.warehouse_name'), prop: 'warehouse_name',show:false },
],
tableOperate:{
show:true,
width:120,
label:this.$t('common.operation')
},
</script>核心代碼分析(重點(diǎn))
columnDropInit(),該方法由sortable提供,實(shí)現(xiàn)了表格的拖拽功能,我這里只寫(xiě)了列拖拽,行拖拽可以自己在官網(wǎng)查看。
watch中的tableHeader,為什么要這么做?因?yàn)楸眍^所展示的數(shù)據(jù),和多選框中被選中項(xiàng)是響應(yīng)關(guān)系,勾選與取消的同時(shí)需要相應(yīng)到表格列的變化。其次表頭綁定的是對(duì)象數(shù)組,額checkbox綁定值只能是字符串或者數(shù)字,原本想直接綁定個(gè)對(duì)象數(shù)組的計(jì)劃泡湯,這是elementui設(shè)計(jì)決定的。(從elementui源碼上解決參考:http://chabaoo.cn/javascript/2852009x5.htm)
tableHeader: {
handler(newVal, oldVal) {
console.log(newVal)
this.checkedHeader = newVal.filter(item => item.show == true)
this.childCheckedItems = this.checkedHeader.map(item => {
return item.label
})
},
immediate: true,
deep: true
}handleCheckedColumChange,子組件通過(guò)$emit觸發(fā)父組件的數(shù)據(jù)變更
handleCheckedColumChange(value) {
this.$emit('changeCheckedColum', value)
},父組件數(shù)據(jù)變更,子組件的watch,再次對(duì)數(shù)據(jù)進(jìn)行監(jiān)聽(tīng)改變
changeCheckedColum(value) {
this.tableHeader.forEach(item => {
if (value.includes(item.label)) {
item.show = true
} else {
item.show = false
}
})
},額外預(yù)留功能點(diǎn)
表格多選

<!-- 勾選框列 --> <el-table-column type="selection" width="48" fixed v-if="needCheckBox"></el-table-column>
上面的勾選框主要用來(lái)對(duì)表格的的數(shù)據(jù)進(jìn)行多選操作,方便以后預(yù)留使用,通過(guò)needCheckBox來(lái)控制是否展示,同時(shí)子組件監(jiān)聽(tīng)該屬性,來(lái)計(jì)算表格拖拽時(shí)的偏移量,在columnDropInit方法中有詳細(xì)注釋?zhuān)?jì)算屬性方法如下:
computed: {
control_index: function () {
return this.needCheckBox ? 1 : 0
},
},表格操作,增刪查改

<!-- 表格操作 子組件-->
<el-table-column :width="tableOperate.width" :label="tableOperate.label" fixed="right" v-if="tableOperate.show">
<template slot-scope="scope">
<slot name="tablerow" :row="scope.row"></slot>
</template>
</el-table-column>
<!--父組件,插槽取值-->
<template v-slot:tablerow="scope">
<el-button type="primary" size="small" @click="editRow(scope.row)">
{{ $t('common.edit') }}
</el-button>
</template>這個(gè)插槽預(yù)留,為了方便表格對(duì)數(shù)據(jù)的增刪查改,通過(guò)插槽傳值,獲取當(dāng)前行的row。
最后
本文主要的是通過(guò),對(duì)需求的拆分與理解,從表格的拖拽,以及列控制,衍生出開(kāi)發(fā)者個(gè)人的開(kāi)發(fā)習(xí)慣,對(duì)組建的預(yù)留以及擴(kuò)展,方便以后使用。再技術(shù)上也有多方面的考量,對(duì)大都數(shù)開(kāi)發(fā)者也有一定的學(xué)習(xí)和參考價(jià)值。好了,本文到此結(jié)束,希望對(duì)你有幫助。
到此這篇關(guān)于Vue.js中el-table表格自定義列控制與拖拽的文章就介紹到這了,更多相關(guān)Vue.js el-table自定義列控制與拖拽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vant?Cascader級(jí)聯(lián)選擇實(shí)現(xiàn)可以選擇任意一層級(jí)
這篇文章主要介紹了vant?Cascader級(jí)聯(lián)選擇實(shí)現(xiàn)可以選擇任意一層級(jí)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
vue-router 路由傳參問(wèn)題(路由傳參方式)
路由傳參主要有兩種方式一種是路徑傳參一種是參數(shù)傳遞,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
Ant?Design?of?Vue?select框獲取key和name的問(wèn)題
這篇文章主要介紹了Ant?Design?of?Vue?select框獲取key和name的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
apache和nginx下vue頁(yè)面刷新404的解決方案
這篇文章主要介紹了apache和nginx下vue頁(yè)面刷新404的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
vue中的vue-router?query方式和params方式詳解
這篇文章主要介紹了vue中的vue-router?query方式和params方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
Vue3+TypeScript實(shí)現(xiàn)二維碼生成組件
在?Web?應(yīng)用中,生成二維碼是常見(jiàn)的需求,本文介紹如何用?Vue3?和?TypeScript?開(kāi)發(fā)一個(gè)二維碼生成組件,支持生成圖片或?canvas?形式的二維碼,并提供豐富的配置選項(xiàng),感興趣的小伙伴跟著小編一起來(lái)看看吧2024-04-04
vue-resource 攔截器interceptors使用詳解
這篇文章主要介紹了vue-resource 攔截器interceptors使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01

