el-table拖拽功能实现(3种详细解释)

本文介绍了如何在Vue的el-table中使用列宽拖拽功能以及如何实现左右table宽度拖拽,同时展示了Sortable.js库在表格列拖拽中的应用,包括setCapture和releaseCapture的使用以及CDN引入方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.el-table自带的列宽拖拽

如图:下方为el-table的属性之一,在下面代码所示的位置加上boder即可,把鼠标放在每个列之间,会出现拖拽的鼠标样式,可以调整列的宽度(但是仅限调整列宽

border是否带有纵向边框booleanfalse
  <!-- 表格 -->
    <el-table
      height="100%"
      width="100%"
      border
      resizable
      v-loading="loading"
      :data="tableData"
      @selection-change="tableSelect"
    >

2.实现左右table宽度拖拽

在使用组件的时候,尽量不要修改他,而是通过控制外面的盒子进行控制

2.1 html主要分为3部分(如图):

2.2 css样式:(样式自行设置)


    ul,li{
      list-style: none;
      display: block;
      margin:0;
      padding:0;
    }
    .lrbox{
      width:100%;
      height: 48%;
      margin: 1% 0px;
      overflow:hidden;
      display: flex;
    }
    .left{
      width:calc(50% - 20px); 
 //注意  calc() 来动态设置宽高,在表达式中运算符的前后必须要有空格
      height:100%;
    }
    .resize {
        cursor: col-resize;
        background-color: #d6d6d6;
        border-radius: 5px;
        margin-top: -10px;
        width: 10px;
        background-size: cover;
        background-position: center;
        /*z-index: 99999;*/
        font-size: 32px;
        color: white;
    }
    .resize:hover {
        color: #4444
    }  
    .mid{
      width:50%;
      height:100%;

    }

2.3 下面是js代码:

多个地方使用可以进行封装混入,提高复用率,减少代码冗余

    dragControlWidth(divWidth,resizeWidth) {  //(最小宽度int,拖动条宽度int)
     //获取
          var resize = document.getElementsByClassName('resize');
          var left = document.getElementsByClassName('left');
          var right = document.getElementsByClassName('mid');
          var box = document.getElementsByClassName('lrbox');
    //对其进行循环,可用于多个左右控制
          for (let i = 0; i < resize.length; i++) {
         //鼠标按下事件
            resize[i].onmousedown = function (e) {
              var startX = e.clientX;    //指针相对于浏览器页面(或客户区)的水平坐标
              resize[i].left = resize[i].offsetLeft;   //返回当前元素相对于 offsetParent 节点左边界的偏移像素值
         //鼠标移动事件
              document.onmousemove = function (e) {
                var endX = e.clientX;
                var moveLen = resize[i].left + (endX - startX); 
                var maxT = box[i].clientWidth - resize[i].offsetWidth; 
        //设置极值范围
                if (moveLen < divWidth) {
                  moveLen = divWidth; 
                }
                if (moveLen > maxT - divWidth){
                  moveLen = maxT  - divWidth;
                }  
       
                resize[i].style.left = moveLen; 
       //用for循环是因为相较消耗小
                for (let j = 0; j < left.length; j++) {
                  left[j].style.width = moveLen + 'px';
                  right[j].style.width = (box[i].clientWidth - moveLen - resizeWidth) + 'px';
                }
              }
          //鼠标抬起事件
              document.onmouseup = function (e) {
          //结束处理(清除事件)
                document.onmousemove = null;
                document.onmouseup = null;
                resize[i].releaseCapture && resize[i].releaseCapture();

              }
              resize[i].setCapture && resize[i].setCapture(); 
              return false;
            }
          }
   
        },

 上方提到了releaseCapturesetCapture ,下面进行简单的解释下呐,嘿嘿

2.4 releaseCapture和setCapture 介绍:

setCapture:

将鼠标事件锁定指定的元素上,当元素捕获了鼠标事件后,该事件只能作用在当前元素上。(上面代码的事件是作用中间的拖动条,拖动条的样式可以自己通过css进行美化,搞出符合自己的想法或者符合需求即可)

使用:

currElement.setCapture(boolean),用于设置是否捕获其子元素鼠标事件

注意:

1.setCapture不可作用于键盘等其它事件,只作用于鼠标事件;

2.setCapture该法是IE浏览器专有;

3.并且只能捕作用在这几个事件上

onmousedown、onmouseup、onmousemove、onclick、ondblclick、onmouseover和onmouseout

releaseCapture:

可以为指定的元素解除事件锁定,与上面的相反,一个锁定一个解锁。

(需要注意使用的是两者必须成对呈现,因为鼠标消息都发给上面锁定的这个窗口,直到调用ReleaseCapture或者调用SetCapture设置另一个窗口为止

另外,还有一个GetCapture,他是专门用来获取是哪个窗口捕获了鼠标事件

2.5 使用了releaseCapturesetCapture两次

还有重要的一点就是代码的后面使用了releaseCapturesetCapture两次

  • 这行代码的目的是检查 resize[i] 元素是否支持 releaseCapture 方法,避免在不支持该方法的浏览器中引发错误
  • 如果 resize[i] 元素支持 releaseCapture 方法,则调用一次 releaseCapture() 来释放鼠标捕获。
  • 使用两次的目的是处理特定情况下的浏览器兼容性问题。在某些浏览器中,需要多次调用 releaseCapture 才能完全释放鼠标捕获。通过使用两次调用,可以确保在各种浏览器环境下都能正确地释放鼠标捕获。

3.利用第3方插件自由拖拽

 Sortable 是一个用于可重新排序的拖放列表JavaScript 库

特征

  • 支持触摸设备和现代浏览器(包括IE9)
  • 可以从一个列表拖动到另一个列表或在同一列表中
  • 移动项目时的 CSS 动画
  • 支持拖动手柄和可选文本(比 voidberg 的 html5sortable 更好)
  • 智能自动滚动
  • 高级掉期检测
  • 流畅的动画
  • 多拖拽支持
  • 支持 CSS 转换
  • 使用原生 HTML5 拖放 API 构建

3.1效果图如下:

3.2使用 NPM 下包及引入:

也可以用pnpm,yarn下载依赖,下载慢可切换源

npm install sortablejs --save

导入到您的项目中:

import Sortable from 'sortablejs';

创建新实例
Sortable.create:HTMLElementObjectSortable  

3.3CDN:

<!-- jsDelivr :: Sortable :: Latest (https://www.jsdelivr.com/package/npm/sortablejs) -->
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>

 3.4代码举例:

3.4.1 使用el-table组件
<template>
	<div class="tablebox">
		<el-table :data="tableData" row-key="id" border highlight-current-row="">
			<el-table-column prop="name" label="你的大名"></el-table-column>
			<el-table-column prop="address" label="地理位置"></el-table-column>
			<el-table-column prop="date" label="那年时候"></el-table-column>
		</el-table>
	</div>
</template>
3.4.2 自定义的数据:

为了演示造的数据,正常应该是调用接口获取数据的

<script>
	import Sortable from 'sortablejs';
	export default {
		data() {
			return {
				tableData: [
					{
						id: '1',
						date: '2023-12-01',
						name: 'Juny Long',
						address: '地球村 亚洲 中国 湖南'
					},
					{
						id: '2',
						date: '2020-12-02',
						name: '琳琳1号',
						address: '地球村 亚洲 中国 贵州'
					},
					{
						id: '3',
						date: '2023-12-03',
						name: '零零七',
						address: '地球村 亚洲 中国 广东'
					},
					{
						id: '4',
						date: '2023-12-04',
						name: '龍',
						address: '地球村 亚洲 中国 香港'
					}
				],
				col: [
					{
						label: '那年时候',
						prop: 'date'
					},
					{
						label: '你的大名',
						prop: 'name'
					},
					{
						label: '地理位置',
						prop: 'address'
					}
				],
				dropCol: [
					{
						label: '那年时候',
						prop: 'date'
					},
					{
						label: '你的大名',
						prop: 'name'
					},
					{
						label: '地理位置',
						prop: 'address'
					}
				]
			}
		},

3.5 执行的方法(从而完成拖拽):

具体解释看代码就行(别跟我说看不懂)


		mounted() {
            //dom加载完成触发
			this.rowDrop();  	// 行
			this.columnDrop();   // 列
		},
		methods: {
			// 行的拖拽
			rowDrop() {
				// 获取需要拖拽的DOM对象
				const tbody = document.querySelector('.el-table__body-wrapper tbody');
                //解决指向问题
				const that = this;
                //创建新实例
				Sortable.create(tbody, {
					// 结束拖拽
					onEnd({ newIndex, oldIndex }) {
                       //   删除当前行,放到拖拽后的位置
						const currentRow = that.tableData.splice(oldIndex, 1)[0];
						that.tableData.splice(newIndex, 0, currentRow);
					}
				})
			},
			// 列的拖拽
			columnDrop() {
			// 获取需要拖拽的DOM对象
				const wrapperTr = document.querySelector('.el-table__body-wrapper tr');
				const that = this;
				Sortable.create(wrapperTr, {
                    //动画
					animation: 180,
                    //延迟
					delay: 0,
					// 结束拖拽
					onEnd: e => {
            console.log(e,'e');
           // 输出新旧的坐标(就是xy行和列的位置,不明白可以看一下输出的哦)
            console.log(e.oldIndex,e.oldDraggableIndex);
            console.log(e.newIndex,e.newDraggableIndex)

						const oldItem = that.dropCol[e.oldIndex];
						that.dropCol.splice(e.oldIndex, 1);
						that.dropCol.splice(e.newIndex, 0, oldItem);
					}
				})
			}
		}
	}
</script>
<style scoped lang="scss">
.tablebox{
  padding: 40px;
  border-radius:10px ;
background-color: #f1f1ee;
}

</style>

3.6 具体官方文档请点击下方进行跳转:

https://www.npmjs.com/package/sortablejs#cdnicon-default.png?t=N7T8https://www.npmjs.com/package/sortablejs#cdn

### Vue3实现 Element Plus 的 `el-table` 和 `el-tree` 组件之间相互拖拽功能 为了实现Vue3 中使用 Element Plus 的 `el-table` 表格组件和 `el-tree` 树形组件之间的数据项相互拖拽,可以采用如下方法: #### 准备工作 确保项目已经安装并配置好 Vue3 及其依赖包以及 Element Plus 库。 #### 安装必要的插件 对于拖拽操作的支持,推荐引入第三方库如 `vuedraggable` 或者基于原生 HTML5 Drag API 来处理复杂的交互逻辑。这里以 `vuedraggable` 为例说明[^1]。 ```bash npm install vuedraggable@next --save ``` #### 创建基础模板结构 创建包含两个主要部分的应用程序布局——一个是用于显示表格的数据列表;另一个是用来展示树形结构的内容区。 ```html <template> <div class="container"> <!-- 左侧:Tree --> <el-card style="width: 40%;"> <draggable :list="treeData" @end="onDragEnd(&#39;tree&#39;)"> <el-tree ref="treeRef" node-key="id" default-expand-all :data="treeData"></el-tree> </draggable> </el-card> <!-- 右侧:Table --> <el-card style="margin-left: 2%; width: 57%;"> <draggable :list="tableData" item-key="id" @end="onDragEnd(&#39;table&#39;)"> <template #item="{ element }"> <el-table-row :row-class-name="&#39;custom-row&#39;" :key="element.id"> <el-table-column prop="name" label="Name"/> <el-table-column prop="value" label="Value"/> </el-table-row> </template> </draggable> </el-card> </div> </template> ``` 注意,在上述代码片段中,通过自定义指令 `draggable` 将拖放行为绑定到了对应的容器上,并且指定了监听事件来捕获结束后的回调函数 `onDragEnd()` 方法。 #### 编写 JavaScript 部分 接下来编写相应的脚本文件,初始化状态变量、设置初始数据源、定义辅助工具函数等。 ```javascript <script setup lang="ts"> import { reactive, onMounted } from &#39;vue&#39;; import draggable from &#39;vuedraggable&#39;; // 初始化 state 数据 const treeData = reactive([ { id: 1, name: "Node One", children: [ { id: 2, name: "Child Node Two" } ] }, ]); const tableData = reactive([ { id: 3, name: "Item Three", value: "" }, { id: 4, name: "Item Four", value: "" }, ]); function onDragEnd(type) { console.log(`Dragging ended at ${type}`); } onMounted(() => {}); </script> ``` 这段 TypeScript 脚本设置了响应式的 `treeData` 和 `tableData` 数组作为各自组件的数据源,并实现了简单的日志记录器 `onDragEnd()` 当任意一项被移动完毕之后触发调用它。 #### 处理跨组件间的拖拽交换 为了让不同类型的条目可以在两者间自由转移,还需要额外考虑一些细节问题,比如当某个元素从一个地方移到另一处时应更新目标集合的状态。这通常涉及到修改原始数组中的索引位置或是直接替换整个对象实例。 可以通过调整 `onDragEnd()` 方法内部的具体业务流程来自定义这些规则。例如,判断当前正在发生的动作发生在哪个区域(即来源于哪一个组件),进而决定如何同步改变对方的数据集。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

じòぴé南冸じょうげん

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值