vue表格拖拽,可以多个单元格拖拽
<template>
<div>
<!-- 手写版本 -->
<div class="flex">
<div class="f-1 flex a-c j-c f-item">
日期
</div>
<div class="f-1 flex a-c j-c f-item">
姓名
</div>
<div class="f-1 flex a-c j-c f-item">
地址
</div>
</div>
<div class="flex" v-for="(item,index) in tableData" :key="index" @drop="drop" @dragover="dragover">
<div
class="f-1 flex a-c j-c td-item handle_move"
:draggable="true"
@dragenter.prevent
@dragover.prevent
@dragstart="dragstart(index,'date')"
@dragenter="dragEnter(index,'date')"
@click="changeItem(item.date,index,'date')"
:class="{'avtive-item':activeCheck(item.date,index,'date')}"
>
{{item.date}}
</div>
<div
class="f-1 flex a-c j-c td-item handle_move"
:draggable="true"
@dragstart="dragstart(index,'name')"
@dragenter.prevent
@dragover.prevent
@dragenter="dragEnter(index,'name')"
@click="changeItem(item.name,index,'name')"
:class="{'avtive-item':activeCheck(item.name,index,'name')}"
>
{{item.name}}
</div>
<div
class="f-1 flex a-c j-c td-item handle_move"
:draggable="true"
@dragstart="dragstart(index,'address')"
@dragenter.prevent
@dragover.prevent
@dragenter="dragEnter(index,'address')"
@click="changeItem(item.address,index,'address')"
:class="{'avtive-item':activeCheck(item.address,index,'address')}"
>
{{item.address}}
</div>
</div>
<!-- el版本 -->
<div style="margin-top: 100px;font-size: 40px;font-weight: bold;">
el-table
</div>
<div @drop="drop" @dragover="dragover">
<el-table :data="tableData" row-key="id">
<el-table-column
v-for="(item, index) in col"
:key="item.prop"
:prop="item.prop"
:label="item.label"
:width="item.prop == 'sort'?'100px':''" >
<!-- 自定义渲染模版 -->
<template slot-scope="scope">
<!-- 当列key为 sort 时,渲染一个手柄icon -->
<template v-if="item.prop =='sort'">
<div class="">
<i :class="scope.row['sort']" />
</div>
</template>
<template v-else>
<div
class="f-1 flex a-c j-c td-item handle_move"
:draggable="true"
@dragenter.prevent
@dragover.prevent
@dragstart="dragstart(scope.$index,item.prop)"
@dragenter="dragEnter(scope.$index,item.prop)"
@click="changeItem(scope.row[`${item.prop}`],scope.$index,item.prop)"
:class="{'avtive-item':activeCheck(scope.row[`${item.prop}`],scope.$index,item.prop)}"
>
{{scope.row[`${item.prop}`]}}
</div>
</template>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
tableData: [
{
id: "1",
date: "2016-05-02",
name: "王小虎1",
address: "上海市普陀区金沙江路 100 弄",
sort: "el-icon-d-caret"
},
{
id: "2",
date: "2016-05-04",
name: "王小虎2",
address: "上海市普陀区金沙江路 200 弄",
sort: "el-icon-d-caret"
},
{
id: "3",
date: "2016-05-01",
name: "王小虎3",
address: "上海市普陀区金沙江路 300 弄",
sort: "el-icon-d-caret"
},
{
id: "4",
date: "2016-05-03",
name: "王小虎4",
address: "上海市普陀区金沙江路 400 弄",
sort: "el-icon-d-caret"
}
],
startKey:'',//开始的key
startIndex:999,//开始的index
endKey:'',//结束的key
endIndex:999,//结束的index
changeObj:{},
trList:['date','name','address'],
changeObjArr:[],
firstClickIndex:-1,//第一次点击的行
col:[
{
label: "日期",
prop: "date"
},
{
label: "姓名",
prop: "name"
},
{
label: "地址",
prop: "address"
},
{
label: "排序",
prop: "sort"
}
]
}
},
methods: {
//单元格结束移动
//ps:仅能单个单元格移动
drop(e){
e.preventDefault()
//如果要做 在本行内替换数据 则打开下面注释
// if(this.firstClickIndex != this.endIndex){
// return;
// }
console.log(this.startKey,'开始的key')
console.log(this.startIndex,'开始的index')
console.log(this.endKey,'结束的key')
console.log(this.endIndex,'结束的key')
console.log(this.changeObj,'勾选的数据')
//如果有一些不需求进行操作的 可以过滤掉 比如说拖拽到date这行 不做处理 则打开下面注释
// if(this.endKey != 'date'){//移入可以做操作的单元格,才执行
// //例如移动的数据替换结束的数据
// //其他操作 。。。
// }
this.$nextTick(()=>{
let trStartIndex = this.trList.indexOf(this.startKey) //开始的key在表头第几个
let trEndIndex = this.trList.indexOf(this.endKey) //结束的key在表头第几个
let diffIndex = trEndIndex - trStartIndex;//下标差值
this.trList.forEach((item,index) => {//循环表头
for(let i in this.changeObj){//for in循环 key与当时选择的下标
if(index == (this.changeObj[i] + diffIndex)){//当选择的下标 + 差值 == 循环表头的下标,即要开始替换数据
this.tableData[this.endIndex][item] = i.split('_')[1]
}
}
})
//做完操作后清空数据
setTimeout(()=>{
this.changeObj = {};
this.changeObjArr = [];
this.firstClickIndex = -1;
this.startKey = ''//开始的key
this.startIndex = 999//开始的index
this.endKey = ''//结束的key
this.endIndex = 999//结束的index
console.log(this.tableData)
},300)
})
},
dragover(e){
e.preventDefault()
},
//拽住移动进入元素内
dragEnter(index,key){
this.endIndex = index;
this.endKey = key;
},
//拽住
dragstart(index,key){
this.startKey = key;
this.startIndex = index;
},
//点击单元格
changeItem(val,index,key){
//如果仅要做单行勾选
if(this.firstClickIndex != -1 && this.firstClickIndex != index){
return;
}
let k = `id_${val}_${key}_${index}`
let ki = this.changeObjArr.indexOf(k);
this.firstClickIndex = index;
if(ki != -1){//再次点击取消选择
this.changeObjArr.splice(ki,1)
delete this.changeObj[k]
}else{
this.$nextTick(()=>{
this.changeObj[k] = this.trList.indexOf(key);
this.changeObjArr.push(k)
})
}
},
//做高亮
activeCheck(val,index,key){
let k = `id_${val}_${key}_${index}`
return this.changeObjArr.includes(k)
}
}
}
</script>
<style scoped>
.handle_move {
cursor: move;
}
.flex{
display: flex;
}
.a-c{
align-items: center;
}
.j-c{
justify-content: center;
}
.f-1{
flex: 1;
}
.t-c{
text-align: center;
}
.f-item{
height: 60px;
background: #F5F6FA;
box-sizing: border-box;
margin: 4px 4px 0 0;
}
.td-item{
height: 80px;
box-sizing: border-box;
margin: 6px 4px 0 0;
background: #FFF2F5;
}
.avtive-item{
border: 1px solid #FF186B;
}
</style>
效果:第一行的1、2单元格从1单元格拖拽到第二行的2单元格,那么第二行的2、3单元格里的数据会被替换成第一行的1、2单元格的数据。