vue3中使用vuedraggable实现拖拽el-tree数据进分组

看效果:

        可以实现单个拖拽、双击添加、按住ctrl键实现多个添加,或者按住shift键实现范围添加,添加到框中的数据,还能拖拽排序

先安装 vuedraggable 

这是他的官网 vue.draggable中文文档 - itxst.com

npm i vuedraggable -S

 直接粘贴代码即可: 

index.vue 

<template><div class="w-full h-full"><!-- 页面拖拽组件 --><div class="leftPart"><ElTreeclass="w100%":data="$.treeData"ref="treeTableListRef":props="$.defaultProps"highlight-current:expand-on-click-node="false"key="id":default-expand-all="true"@node-click="(data, node) => $.tableFieldsNodeClick(data, node, treeTableListRef)"><template #default="{ data }"><Draggable:list="[data]"ghost-class="ghost"chosen-class="chosenClass"animation="300"@start="onStart"@end="onEnd"group="group1"v-tooltip="`Tips:按住Ctrl或Shift进行批量选择`"><template #item="{ element }"><div @dblclick="dbAddData(element)" style="user-select: none" class="item">{{ element.name }}</div></template></Draggable></template></ElTree></div><!-- 右侧内容 --><div class="rightPart"><div class="flex"><div@mouseover="divMouseOver"@mouseleave="divMouselease"class="w-full rightContent"style="border: 1px solid #ccc"><Draggable:list="state.list"ghost-class="ghost"group="group1"chosen-class="chosenClass"animation="300"@start="onStart"@end="onEnd"@add="addData"class="w-full dragArea"><template #item="{ element }"><div class="item">{{ element.name }}</div></template></Draggable></div></div></div></div>
</template><script setup lang="ts">
import Draggable from "vuedraggable";
import { useData } from "./hooks/drag";
const treeTableListRef = ref();
let { $data: $ } = useData();
const state = reactive<any>({//需要拖拽的数据,拖拽后数据的顺序也会变化list: [],
});
//拖拽开始的事件
const onStart = () => {console.log("开始拖拽");
};
const divMouseOver = (e: any) => {};
const divMouselease = (e: any) => {};
//拖拽结束的事件
const onEnd = () => {console.log("结束拖拽");
};
// 双击添加
const dbAddData = (data: any) => {let i = state.list.findIndex((a: any) => a.id == data.id);if (data.children) return; //父级节点不添加if (i == -1) state.list.push(data);
};
// 批量添加
const addData = () => {// 拿到所有nodes节点数组const nodes = treeTableListRef.value.store._getAllNodes();nodes.map((a: any) => {if ($.selectNodes.includes(a.id)) {state.list.push(a.data);}// 排除父级,只添加子级state.list = state.list.filter((a: any) => !a.children);// 去重state.list = [...new Set(state.list)];});
};
onMounted(() => {});
onBeforeMount(() => {window.addEventListener("keydown", handleKeyDown);window.addEventListener("keyup", handleKeyUp);
});
// 按下为true
const handleKeyDown = (event: any) => {// 代表按下的是ctrl键if (event.key == "Control") {$.ctrlKeyPressed = true;}// 代表按下的是shift键if (event.key == "Shift") {$.shiftKeyPressed = true;}
};
// 释放为false
const handleKeyUp = (event: any) => {// 代表按下的是ctrl键if (event.key == "Control") {$.ctrlKeyPressed = false;}// 代表按下的是shift键if (event.key == "Shift") {$.shiftKeyPressed = false;}
};
</script><style scoped lang="scss">
.leftPart {width: 20%;height: 100%;float: left;border-right: 1px dashed #ccc;
}
.rightPart {padding: 20px;width: 60%;height: 100%;float: left;
}
.list_drap {min-width: 120px;max-height: 86px;min-height: 22px;overflow-y: auto;height: auto;
}
.rightContent {border-radius: 4px;min-height: 30px;display: flex;
}
.dragArea {padding: 10px 5px;flex-grow: 1;.item {float: left;min-width: 50px;display: inline;margin: 0 3px 2px 3px;background-color: rgb(235, 241, 255);color: #3370ff;font-size: 12px;cursor: all-scroll;user-select: none;height: 20px;line-height: 20px;padding-left: 9px;padding-right: 9px;background: #ececfd;color: #333333;font-size: 12px;}
}
</style>

drag.ts

export function useData() {const $data: any = reactive({ctrlKeyPressed: false,shiftKeyPressed: false,shiftKeyFelid: [],defaultProps: {children: "children",label: "name",},treeData: [{name: "一级1",id: 1,children: [{name: "二级1",id: 2,children: [{name: "三级1",id: 2,},{name: "三级2",id: 4,},{name: "三级3",id: 5,},{name: "三级4",id: 6,},{name: "三级5",id: 7,},],},{name: "二级2",id: 8,},{name: "二级3",id: 9,},{name: "二级4",id: 10,},{name: "二级5",id: 11,},],},{name: "一级2",id: 12,children: [{name: "二级1",id: 13,},{name: "二级2",id: 14,},{name: "二级3",id: 15,},{name: "二级4",id: 16,},{name: "二级5",id: 17,},],},],selectNodes: [],treeTableListRef: null,});// 节点选中事件$data.tableFieldsNodeClick = (nodeData: any, node: any, treeTableListRef: any) => {const nodes = treeTableListRef.store._getAllNodes(); //所有node节点const ishas = $data.selectNodes.includes(node.id);// 递归遍历节点数组进行ID存放function addSelectId(arr: any) {for (const item of arr) {$data.selectNodes.push(item.id);if (Array.isArray(item.childNodes) && item.childNodes.length) {addSelectId(item.childNodes);}}}// 递归遍历删除节点idfunction delSelectId(arr: any) {for (const item of arr) {const index = $data.selectNodes.findIndex((x: any) => x == item.id);$data.selectNodes.splice(index, 1);if (Array.isArray(item.children) && item.children.length) {delSelectId(item.children);}}}// 按住了ctrl键,可以进行单个多选if ($data.ctrlKeyPressed) {// 如果为true代表当前选中的节点已存在if (ishas) {// 查找当前选中的节点的索引const index = $data.selectNodes.findIndex((x: any) => x == node.id);// 删除父节点$data.selectNodes.splice(index, 1);// 删除子节点if (Array.isArray(node.childNodes) && node.childNodes.length) {delSelectId(node.childNodes);}} else {// 否则当前选中的节点不存在,就加入到已选节点数组序列$data.selectNodes.push(node.id);// 防止选中的是父节点,就需要递归将子节点加入if (Array.isArray(node.childNodes) && node.childNodes.length) {addSelectId(node.childNodes);}}node.isCurrent = !node.isCurrent;// 按下了shift键,可以进行范围多选} else if ($data.shiftKeyPressed) {// 先清空$data.selectNodes = [];// 将当前节点放入$data.selectNodes.push(node.id);$data.shiftKeyFelid.push(node.id);if ($data.shiftKeyFelid.length > 1) {// 首索引const sIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[0]);// 尾索引const eIndex = nodes.findIndex((x: any) => x.id == $data.shiftKeyFelid[$data.shiftKeyFelid.length - 1]);// 根据首尾索引,存入中间节点const s = sIndex < eIndex ? sIndex : eIndex; //取小值当开头索引const e = sIndex < eIndex ? eIndex : sIndex; //取大值当结尾索引for (let i = s; i < e; i++) {$data.selectNodes.push(nodes[i].id);}}} else {// 否则就是单机选择$data.shiftKeyFelid = [];$data.selectNodes = [];$data.selectNodes = [node.id];}// 下面是对已选中的节点,进行高亮展示// 通过控制elementui中节点上的isCurrent属性// isCurrent为true是高亮,否则取消高亮for (const item of nodes) {if ($data.selectNodes.includes(item.id)) {item.isCurrent = true;} else {item.isCurrent = false;}}};return {$data: $data,};
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/485427.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构建高效稳定的外卖平台架构设计与实现

外卖行业的快速发展为人们的生活带来了便利&#xff0c;随着外卖市场的扩大和竞争的加剧&#xff0c;外卖平台的架构设计变得至关重要。一个高效稳定的架构可以支持平台的快速发展&#xff0c;提供优质的服务体验&#xff0c;同时保障用户数据的安全性。 用户端架构设计 移动端…

11.CSS3的媒介(media)查询

CSS3 的媒介(media)查询 经典真题 如何使用媒体查询实现视口宽度大于 320px 小于 640px 时 div 元素宽度变成 30% 媒体查询 媒体查询英文全称 Media Query&#xff0c;顾名思义就是会查询用户所使用的媒体或者媒介。 在现在&#xff0c;网页的浏览终端是越来越多了。用户可…

【elementUi-table表格】 滚动条 新增监听事件; 滚动条滑动到指定位置;

1、给滚动条增加监听 this.dom this.$refs.tableRef.bodyWrapperthis.dom.scrollTop 0let _that thisthis.dom.addEventListener(scroll, () > {//获取元素的滚动距离let scrollTop _that.dom.scrollTop//获取元素可视区域的高度let clientHeight this.dom.clientHeigh…

vue实现拖拽(vuedraggable)

实现效果: 左侧往右侧拖动&#xff0c;右侧列表可以进行拖拽排序。 安装引用&#xff1a; npm install vuedraggable import draggable from vuedraggable 使用&#xff1a; data数据&#xff1a; componentList: [{groupName: 考试题型,children: [{componentType: danxua…

Ansible安装管理和模块的使用

目录 Ansible是什么 ansible 环境安装部署 管理端安装 ansible ansible 目录结构 配置主机清单 配置密钥对验证 ansible 命令行模块 1&#xff0e;command 模块 在远程主机执行命令&#xff0c;不支持管道&#xff0c;重定向等shell的特性 常用的参数 2&#xff0e;sh…

bat 查找文件所在

脚本 在批处理文件&#xff08;.bat&#xff09;中查找文件所在的目录&#xff0c;你可以使用dir命令结合循环和条件语句来实现。以下是一个简单的示例&#xff0c;演示如何在批处理文件中查找指定文件并输出其所在目录&#xff1a; echo off setlocal enabledelayedexpansio…

Elasticsearch从入门到精通-01认识Elasticsearch

Elasticsearch从入门到精通-01认识Elasticsearch &#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是程序员行走的鱼 &#x1f342;博主从本篇正式开始ES学习&#xff0c;希望小伙伴可以一起探讨 &#x1f4d6; 本篇主要介绍和大家一块简单认识下ES并了解ES中的主要角色…

MySQL 窗口函数温故知新

本文用于复习数据库窗口函数&#xff0c;希望能够温故知新&#xff0c;也希望读到这篇文章的有所收获。 本文以&#xff1a;MySQL为例 参考文档&#xff1a; https://www.begtut.com/mysql/mysql-window-functions.html 使用的样例数据&#xff1a;https://www.begtut.com/m…

vue3新特性-defineOptions和defineModel

defineOptions 背景说明&#xff1a; 有 <script setup> 之前&#xff0c;如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。 但是用了 <script setup> 后&#xff0c;就没法这么干了 setup 属性已经没有了&#xff0c;自然无法添加与其平…

R语言【base】——abs(),sqrt():杂项数学函数

Package base version 4.2.0 Description abs(x) 计算 x 的绝对值&#xff0c;sqrt(x) 计算 x 的正平方根。 Usage abs(x) sqrt(x) Arguments 参数【x】&#xff1a;一个数值或复数向量或数组。 Details 这些都是内部泛型原语函数:可以为它们单独定义方法&#xff0c;也可以…

IDEA启动Springboot报错:无效的目标发行版:17 的解决办法

无效的目标发行版&#xff1a;17 的解决办法 一般有两个原因&#xff0c;一可能是本地没有安装JDK17&#xff0c;需要安装后然后在IDEA中选择对应版本&#xff1b;二可能是因为IDEA版本太低&#xff0c;不支持17&#xff0c;需要升级IDEA版本。然后在File->Project Struct…

【Java EE初阶二十】http的简单理解(一)

1. 初识http HTTP 最新的版本应该是 HTTP/3.0&#xff0c;目前大规模使用的版本 HTTP/1.1&#xff1b; 下面来简单说明一下使用 HTTP 协议的场景: 1、浏览器打开网站 (基本上) 2、手机 APP 访问对应的服务器 (大概率) 前面的 TCP与UDP 和http不同&#xff0c;HTTP 的报文格式&a…