vue和H5 draggable实现拖拽并替换效果


Posted in Javascript onJuly 29, 2020

前言

公司项目需要做拖拽替换效果,本人用的vue框架。在网上找了很多资料都是用的 Vue.Draggable(git地址)。但这个组件实现的拖拽后插入效果,我倒腾了很久也没有替换效果(如果Vue.Draggable能实现拖拽替换效果的话请大神给我留言)。

JQ有实现拖拽的插件,我下载过一个插件并看过源码,大致原理是给目标元素设置定位属性,通过监听鼠标mousedown,mouseup事件,再计算鼠标位置变化,然后给元素样式设置偏移值来实现拖拽效果的。

H5提供了专门的拖拽API 给元素添加 draggable 属性,设置为 true就能实现拖拽了。本文使用的H5提供的拖拽API 以及vue 无其他任何添加,请放心使用

直接上代码

<template>
 <div class="container">
  <div class="layout">
   <button
    class="layout-btn"
    @click="layoutType=val.value"
    v-for="val in layoutOptions"
    :key="val.value"
   >{{val.label}}</button>
  </div>

  <div
   class="group"
   :class="{'left-top-container': gindex===0,
    'right-top-container': gindex===1,
    'bottom-container': gindex===2,
    'top-container': gindex<2}"
   v-for="(group,gindex) in data"
   :key="gindex"
  >
   <div
    class="cls-default"
    v-for="(item,cindex) in group.children"
    :key="cindex"
    :data-id="gindex+'-'+cindex"
    draggable="true"
    @dragstart="onDragstart($event)"
    @dragend="onDragend($event)"
    @dragover="onDragover($event)"
    @drop="onDrop($event)"
    :style="{'background-color': item.color}"
    :class="{'cls1-0': cindex ===0 && layoutType==1,
    'cls2-0': (cindex ===0 || cindex ===1) && layoutType==2,
    'cls3-0': cindex ===0 && layoutType==3,
    'cls3-1': (cindex ===1 || cindex ===2) && layoutType==3,
    'cls4-0': cindex <4 && layoutType==4,
    'cls6-0': cindex === 0 && layoutType==6
    }"
   >
    <div class="content">{{item.color ? item.color : '我是空对象'}}</div>
   </div>
  </div>
  <div class="tips">上面两个区域内是展示区的内容能互相拖拽
   <br>下面的是资源区,只能复制出去覆盖目标区域,本身不会被替换掉
  </div>
 </div>
</template>

<script>
export default {
 data() {
  return {
   stargindex: "",
   endIndex: "",
   layoutType: "9",
   layoutOptions: [
    { label: "单分屏", value: 1 },
    { label: "二分屏", value: 2 },
    { label: "三分屏", value: 3 },
    { label: "四分屏", value: 4 },
    { label: "六分屏", value: 6 },
    { label: "九分屏", value: 9 }
   ],
   data: [
    {
     group: "left-show",
     title: "视频播放区一",
     children: [
      {
       id: 6,
       color: "orange"
      },
      {
       id: 2,
       color: "yellow"
      },
      {},
      {},
      {},
      {},
      {
       id: 3,
       color: "cyan"
      },
      {},
      {
       id: 5,
       color: "brown"
      }
     ]
    },
    {
     group: "right-show",
     title: "视频播放区二",
     children: [
      {},
      {
       id: 7,
       color: "pink"
      },
      {},
      {},
      { id: 4, color: "purple" },
      {},
      {},
      {},
      {
       id: 10,
       color: "gray"
      }
     ]
    },
    {
     group: "source",
     title: "视频资源区",
     children: [
      {
       id: 11,
       color: "white"
      },
      {
       id: 12,
       color: "black"
      },
      {
       id: 13,
       color: "red"
      },
      {
       id: 14,
       color: "green"
      },
      {
       id: 15,
       color: "blue"
      }
     ]
    }
   ]
  };
 },
 methods: {
  onDragstart(event) {
   this.stargindex = event.target.getAttribute("data-id");
  },
  onDragend(event) {
   let startGroupIndex = this.stargindex.split("-")[0];
   let startChildIndex = this.stargindex.split("-")[1];
   let endGroupIndex = this.endIndex.split("-")[0];
   let endChildIndex = this.endIndex.split("-")[1];
   // 对数据做简单的深拷贝 目前不需要
   // let endObj = JSON.parse(
   //  JSON.stringify(this.data[endGroupIndex].children[endChildIndex])
   // );
   // let startObj = JSON.parse(
   //  JSON.stringify(this.data[startGroupIndex].children[startChildIndex])
   // );
   let endObj = this.data[endGroupIndex].children[endChildIndex];
   let startObj = this.data[startGroupIndex].children[startChildIndex];
   if (this.data[endGroupIndex].group === "source") {
    //往资源区拖拽时 不做任何替换操作
    return;
   }
   this.data[endGroupIndex].children.splice(endChildIndex, 1, startObj);
   if (this.data[startGroupIndex].group !== "source") {
    //拖拽起始区域不是 source时 把起始区域替换成拖拽后区域的数据
    this.data[startGroupIndex].children.splice(startChildIndex, 1, endObj);
   }
  },
  onDrop(event) {
   if (event.target.className.indexOf("cls-default") > -1) {
    this.endIndex = event.target.getAttribute("data-id");
   } else {
    this.endIndex = event.target.parentElement.getAttribute("data-id");
   }
  },
  onDragover(event) {
   event.preventDefault();
  }
 }
};
</script>

<style scoped>
.container {
 background-color: #eee;
 height: 800px;
}
.layout .layout-btn {
 background-color: #409eff;
 color: #fff;
 padding: 10px 15px;
 margin: 10px 15px;
}
.tips {
 font-size: 24px;
 text-align: center;
}
.group {
 float: left;
 overflow: hidden;
 box-sizing: border-box;
}
.group-title {
 height: 40px;
 line-height: 40px;
}
.cls-default {
 float: left;
 margin: 0;
 box-sizing: border-box;
 overflow: hidden;
 border: 1px solid #999;
}
.cls-default .content {
 text-align: center;
 padding-top: 20px;
 font-size: 20px;
}
.top-container {
 height: 400px;
 width: 40%;
 margin: 15px 5%;
}
.top-container .cls-default {
 width: 33.33%;
 height: 33.33%;
}
.top-container .cls1-0 {
 width: 100%;
 height: 100%;
}
.top-container .cls2-0 {
 width: 50%;
 height: 100%;
}
.top-container .cls3-0 {
 width: 50%;
 height: 100%;
}
.top-container .cls3-1 {
 width: 50%;
 height: 50%;
}
.top-container .cls4-0 {
 width: 50%;
 height: 50%;
}
.top-container .cls6-0 {
 width: 66.66%;
 height: 66.65%;
}
.bottom-container {
 width: 90%;
 height: 200px;
 margin: 15px 5%;
}
.bottom-container .cls-default {
 width: 15%;
 height: 150px;
}
</style>

写在最后

本文是我第一次写博客,写的比较随意,样式处理也是很随心。如有错误请指正。

后面有时间会完善组件的功能。参考Vue.Draggable(git地址)这个组件。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js获取RadioButtonList的Value/Text及选中值等信息实现代码
Mar 05 Javascript
简单实现JS对dom操作封装
Dec 02 Javascript
简单了解JavaScript操作XPath的一些基本方法
Jun 03 Javascript
javascript类型系统——undefined和null全面了解
Jul 13 Javascript
深入学习Bootstrap表单
Dec 13 Javascript
dropload.js插件下拉刷新和上拉加载使用详解
Oct 20 Javascript
浅谈使用React.setState需要注意的三点
Dec 18 Javascript
jquery 给动态生成的标签绑定事件的几种方法总结
Feb 24 jQuery
vue数据操作之点击事件实现num加减功能示例
Jan 19 Javascript
vue实现动态显示与隐藏底部导航的方法分析
Feb 11 Javascript
JavaScript实现英语单词题库
Dec 24 Javascript
springboot+VUE实现登录注册
May 27 Vue.js
vue同个按钮控制展开和折叠同个事件操作
Jul 29 #Javascript
JavaScript编写开发动态时钟
Jul 29 #Javascript
js编写简易的计算器
Jul 29 #Javascript
从0到1学习JavaScript编写贪吃蛇游戏
Jul 28 #Javascript
javascript如何使用函数random来实现课堂随机点名方法详解
Jul 28 #Javascript
Node.js 深度调试方法解析
Jul 28 #Javascript
vue-列表下详情的展开与折叠案例
Jul 28 #Javascript
You might like
深入PHP操作MongoDB的技术总结
2013/06/02 PHP
浅谈php+phpStorm+xdebug配置方法
2015/09/17 PHP
通过javascript设置css属性的代码
2009/12/28 Javascript
jQuery操作Select选择的Text和Value(获取/设置/添加/删除)
2013/03/06 Javascript
js中的this关键字详解
2013/09/25 Javascript
利用a标签自动解析URL分析网址实例
2014/10/20 Javascript
编写简单的jQuery提示插件
2014/12/21 Javascript
浅谈javascript中的闭包
2015/05/13 Javascript
Ionic默认的Tabs模板使用实例
2016/08/29 Javascript
关于JS中二维数组的声明方法
2016/09/24 Javascript
如何判断出一个js对象是否一个dom对象
2016/11/24 Javascript
bootstrap轮播图示例代码分享
2017/05/17 Javascript
JavaScript条件判断_动力节点Java学院整理
2017/06/26 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
详解如何理解vue的key属性
2019/04/14 Javascript
JS端基于download.js实现图片、视频时直接下载而不是打开预览
2020/05/09 Javascript
[01:40]2014DOTA2国际邀请赛 三冰SOLO赛后采访恶搞
2014/07/09 DOTA
[01:05:24]Ti4 冒泡赛第二天 iG vs NEWBEE 3
2014/07/15 DOTA
Python安装第三方库及常见问题处理方法汇总
2016/09/13 Python
python进程管理工具supervisor的安装与使用教程
2017/09/05 Python
对python读写文件去重、RE、set的使用详解
2018/12/11 Python
python-序列解包(对可迭代元素的快速取值方法)
2019/08/24 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
python实现两个字典合并,两个list合并
2019/12/02 Python
python:目标检测模型预测准确度计算方式(基于IoU)
2020/01/18 Python
使用SQLAlchemy操作数据库表过程解析
2020/06/10 Python
德国箱包网上商店:koffer24.de
2016/07/27 全球购物
介绍一下JNDI的基本概念
2013/07/26 面试题
环境科学专业个人求职信
2013/09/26 职场文书
环境建设实施方案
2014/03/14 职场文书
离职报告格式
2014/11/04 职场文书
政风行风整改报告
2014/11/06 职场文书
2014年个人师德工作总结
2014/12/04 职场文书
经验交流材料格式
2014/12/30 职场文书
spring项目中切面及AOP的使用方法
2021/06/26 Java/Android
mybatis3中@SelectProvider传递参数方式
2021/08/04 Java/Android