当前位置: 首页 > article >正文

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单元格的数据。
在这里插入图片描述
在这里插入图片描述


http://www.kler.cn/a/539638.html

相关文章:

  • 每日一题——没有重复项数字的全排列
  • 【Java基础】为什么不支持多重继承?方法重载和方法重写之间区别、Exception 和 Error 区别?
  • c++ haru生成pdf输出饼图
  • TCP三次握手全方面详解
  • CF998A Balloons​ 构造 ​
  • 高并发读多写少场景下的高效键查询与顺序统计的方案思路
  • html 列动态布局
  • 2025年2月份的一次前端面试题记录....
  • 使用Redis解决使用Session登录带来的共享问题
  • 深度学习-利用Tacotron 2 和 WaveGlow 模型 进行语音合成
  • Vue引入外部异步js函数并接收返回值
  • mysql中主键索引和联合索引的原理解析
  • 开源堡垒机 JumpServer 社区版实战教程:基于 Ubuntu 22.04 离线安装 JumpServer 社区版 v4.4.1
  • 变化检测论文阅读合集
  • 激活函数篇 01 —— 激活函数在神经网络的作用
  • vue3+vite+ts项目中使用vue-router
  • OnlyOffice文件转换PDF
  • 【豆包Marscode体验官】揭秘MarsCode AI编辑助手:高效智能编辑新纪元之入门指导与最佳实践
  • 使用 OpenGL ES 渲染一个四边形
  • 亚马逊爬虫实战:中国商家信息(电话)爬取
  • 6.Centos7上部署flask+SQLAlchemy+python+达梦数据库
  • JVM 知识总结
  • 物联网软件开发与应用方向应该怎样学习,学习哪些内容,就业方向是怎样?(文末领取整套学习视频,课件)物联网硬件开发与嵌入式系统
  • CNN-day6-经典神经网络AlexNet
  • ubuntu server环境下使用mitmproxy代理
  • Protobuf为何成为高效数据交换的首选?