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

draggable组件实现两层拖拽面板

遇见情况:现在的数据层层叠叠,有的要求不仅简单的单个盒子拖拽,而且要求:父盒子里面的子盒子也要能拖拽。

实现要求:拖拽父输入框只能与属于父输入框的交换位置;拖拽子输入框只能与子输入框交换位置

实现图片:

完整代码实现:

<template> <div class="custom no-select"> <el-form :model="formtwo" ref="formRef" label-width="auto" style="max-width: 475px" > <draggable v-model="formtwo.dimensionalInfoList" item-key="id" handle=".drag-handle" animation="300" @end="onEnd" > <template #item="{ element: group, index: groupIndex }"> <div class="group_card"> <!-- 父维度 --> <div class="father_box"> <span class="iconfont icon-hengxian drag-handle"></span> <el-form-item :prop="'dimensionalInfoList.' + groupIndex + '.content'" :rules="{ required: true, message: '父维度不能为空', trigger: 'blur', }" > <el-input v-model="group.content" placeholder="请输入父分析维度" class="desc__content" /> </el-form-item> <SisternodeOutlined class="icon_Share_css" :style="{ marginRight: formtwo.dimensionalInfoList.length === 1 ? '24px' : '10px', }" @click="addNextInput(groupIndex)" /> <el-icon class="icon_height_css" v-if="formtwo.dimensionalInfoList.length !== 1" > <CircleClose @click="delInput(groupIndex)" /> </el-icon> </div> <!-- 子维度 --> <draggable v-model="group.childInfo" item-key="id" handle=".drag-handle" animation="300" @end="onEnd" > <template #item="{ element: groupChild, index: groupIndexChild }"> <div class="groupChild_card"> <!-- 前方样式引导,用于连接父节点和子节点的连线--> <div style=" width: 30px; height: 50px; float: left; margin-top: -24px; " > <div style="display: flex"> <div :style="{ height: groupIndexChild !== group.childInfo.length - 1 ? '40px' : '35px', paddingLeft: '7px', borderRight: '1px solid #979797', }" ></div> <div style=" width: 20px; height: 6px; margin-top: 34px; border-left: 1px solid #979797; border-bottom: 1px solid #979797; border-radius: 0 0 0 5px; margin-left: -0.5px; " ></div> </div> <div style=" width: 0.5px; height: 10px; background-color: #979797; float: left; margin-left: 7px; " v-if="groupIndexChild !== group.childInfo.length - 1" ></div> </div> <span class="iconfont icon-hengxian drag-handle"></span> <el-form-item :prop=" 'dimensionalInfoList.' + groupIndex + '.childInfo.' + groupIndexChild + '.content' " :rules="{ required: true, message: '子维度不能为空', trigger: 'blur', }" > <el-input v-model="groupChild.content" placeholder="请输入子分析维度" class="desc__content desc__content_son" /> </el-form-item> <el-icon class="icon_height_css"> <CircleClose @click="delInputSon(child)" /> </el-icon> </div> </template> </draggable> </div> </template> </draggable> </el-form> </div> </template> <script setup> import { ref } from "vue"; import { CircleClose } from "@element-plus/icons-vue"; import { SisternodeOutlined } from "@ant-design/icons-vue"; import draggable from "vuedraggable"; let i = 1; //自定义id const formRef = ref(); //定义分析维度表单 // 分析维度,初始化就显示三个框 const formtwo = ref({ dimensionalInfoList: [ { content: "", dimId: ++i, childInfo: [] }, { content: "", dimId: ++i, childInfo: [] }, { content: "", dimId: ++i, childInfo: [] }, ], }); //拖拽结束事件,重新更新数据 const onEnd = () => { }; // 添加子联动输入框 const addNextInput = (index) => { // 获取当前维度对象 const currentItem = formtwo.value.dimensionalInfoList[index]; if (!currentItem.childInfo) { currentItem.childInfo = []; } // 向当前维度对象的 childInfo 数组中添加一个新的子维度对象 currentItem.childInfo.push({ content: "", }); }; // 删除维度输入框 const delInput = (index) => { formtwo.value.dimensionalInfoList.splice(index, 1); }; // 删除子维度输入框 const delInputSon = (child) => { // 找到当前子维度对应的父维度对象 const parentIndex = formtwo.value.dimensionalInfoList.findIndex((item) => item.childInfo.includes(child), ); const parentItem = formtwo.value.dimensionalInfoList[parentIndex]; // 从父维度对象的 childInfo 数组中删除当前子维度对象 parentItem.childInfo = parentItem.childInfo.filter((item) => item !== child); }; </script> <style lang="scss" scoped> .father_box { display: flex; justify-content: start; width: 100%; .icon_Share_css { text-align: center; margin-top: 15px; color: rgb(151, 151, 151); cursor: pointer; margin-right: 10px; } .icon_Share_css :hover { color: #1363df; } } .icon_height_css { text-align: center; line-height: 30px; margin-top: 15px; color: rgb(151, 151, 151) !important; cursor: pointer; } .icon_height_css :hover { color: red; } .desc__content { margin-left: 10px; margin-right: 10px; width: 100%; :deep .el-textarea__inner { background-color: rgba(246, 246, 246); min-height: 50px; max-height: 200px; } :deep .el-input__wrapper { background-color: rgba(246, 246, 246); } } .adddome { width: 100%; font-size: 12px; line-height: 12px; float: left; display: flex; justify-content: space-between; padding-bottom: 16px; .icon-gengxin { color: #979797; font-size: 15px; margin-right: 0; } .icon-gengxin:hover { color: #1363df; } } .icon-hengxian { font-size: 15px; color: #979797; text-align: center; line-height: 30px; cursor: move; } :deep .el-form-item__error { margin-left: 25px; } .son :deep .el-form-item__error { margin-left: 50px !important; } .prependInput { margin-bottom: 15px; } :deep .el-input-group--prepend > .el-input__wrapper, .el-input-group__append { background-color: rgba(246, 246, 246) !important; } :deep .el-input-group__prepend { background-color: rgba(246, 246, 246) !important; } .no-select { user-select: none; } .group_card { .groupChild_card { display: flex; width: 95%; } } .el-form-item { width: 100%; } </style>

注意点:

1、拖拽的id必须要有,要不然不能进行拖拽

2、handle=".drag-handle"为draggable组件的拖拽盒子的css,所以要在导入的icon图标上添加上该className

3、且template下方必须只有一个item的slot——必须只有一个子节点

4、子维度在父维度内部,

5、关于图片上父节点与子节点的连线是html手动调整实现,所以你们要写的时候需要根据实际情况进行调整

<!-- 前方样式引导,用于连接父节点和子节点的连线--> <div style=" width: 30px; height: 50px; float: left; margin-top: -24px; " > <div style="display: flex"> <div :style="{ height: groupIndexChild !== group.childInfo.length - 1 ? '40px' : '35px', paddingLeft: '7px', borderRight: '1px solid #979797', }" ></div> <div style=" width: 20px; height: 6px; margin-top: 34px; border-left: 1px solid #979797; border-bottom: 1px solid #979797; border-radius: 0 0 0 5px; margin-left: -0.5px; " ></div> </div> <div style=" width: 0.5px; height: 10px; background-color: #979797; float: left; margin-left: 7px; " v-if="groupIndexChild !== group.childInfo.length - 1" ></div> </div>
http://www.gsyq.cn/news/182286.html

相关文章:

  • 2026年AI大变局!模型竞赛落幕,Agent竞赛开启,收藏这篇看懂未来3年技术走向
  • 从零开始:用Miniconda-Python3.9跑通PyTorch GPU模型
  • 深入解析字符串:从基础到高效应用
  • Linux find命令查找Miniconda环境中的大文件
  • Jupyter Notebook密码保护设置:Miniconda安全指南
  • 自动化数据清洗流程:Miniconda-Python3.9+Pandas脚本
  • Miniconda-Python3.9镜像跨平台兼容性测试报告
  • 普通二本程序员除了外包还有别的路吗?
  • 智能掌控温度,安全预见未来:ATE800无线测温装置,为工业安全保驾护航
  • Markdown嵌入视频链接:技术分享更直观
  • Docker prune清理无用Miniconda镜像节省存储
  • Linux驱动proc接口示例源码分析
  • GPU共享内存设置:PyTorch训练性能优化
  • pikachu-RCE,越权,目录遍历
  • Jupyter Lab插件推荐:Miniconda用户提升生产力
  • D2225UK,多用途硅DMOS射频场效应晶体管, 现货库存
  • Linux系统监控脚本:基于Miniconda-Python3.9实时查看资源
  • 学AI不必花大钱配显卡:6G老笔记本也能跑起来,2个月入门实战经验
  • HTML表单提交处理:Miniconda-Python接收用户输入
  • Token长度与成本关系分析:合理规划API调用
  • ARP欺骗
  • Markdown TOC自动生成:提高长篇文档导航效率
  • 【左扬精讲】| kafka_exporter v1.9.0 源码专题 | 架构设计与实现原理全解析
  • Silvaco TCAD | 铁电晶体管FeFET原理与仿真
  • 网络安全发展趋势与转行案例分析:机遇与挑战并存系列一
  • day 45
  • Miniconda-Python3.9镜像安全性分析:适合企业级应用吗?
  • IT运维不只有主业!22个副业方向让你实现“财富自由”!
  • Pyenv virtualenv创建Python3.9环境详细步骤
  • 零基础转行网络安全运维?学习顺序搞错=白费功夫!