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 相关文章推荐
JQuery Tips(4) 一些关于提高JQuery性能的Tips
Dec 19 Javascript
Javascript下IE与Firefox下的差异兼容写法总结
Jun 18 Javascript
给应用部分的js代码设定一个统一的入口
Jun 15 Javascript
JS实现常见的TAB、弹出层效果(TAB标签,斑马线,遮罩层等)
Oct 08 Javascript
vue中的模态对话框组件实现过程
May 01 Javascript
vue中v-for通过动态绑定class实现触发效果
Dec 06 Javascript
浅谈在Vue.js中如何实现时间转换指令
Jan 06 Javascript
Javascript删除数组里的某个元素
Feb 28 Javascript
node获取客户端ip功能简单示例
Aug 24 Javascript
JavaScript多种图形实现代码实例
Jun 28 Javascript
vue 获取url参数、get参数返回数组的操作
Nov 12 Javascript
js实现有趣的倒计时效果
Jan 19 Javascript
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 获取MySQL数据库里所有表的实现代码
2011/07/13 PHP
php中获取主机名、协议及IP地址的方法
2014/11/18 PHP
Laravel使用memcached缓存对文章增删改查进行优化的方法
2016/10/08 PHP
PHP观察者模式实例分析【对比JS观察者模式】
2019/05/22 PHP
JavaScript 直接操作本地文件的实现代码
2009/12/01 Javascript
JavaScript可否多线程? 深入理解JavaScript定时机制
2012/05/23 Javascript
jQuery判断iframe中元素是否存在的方法
2013/05/11 Javascript
jquery 定位input元素的几种方法小结
2013/07/28 Javascript
JS阻止冒泡事件以及默认事件发生的简单方法
2014/01/17 Javascript
JavaScript中的console.trace()函数介绍
2014/12/29 Javascript
JavaScript电子时钟倒计时第二款
2016/01/10 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
2016/09/26 Javascript
jQuery点击头像上传并预览图片
2017/02/23 Javascript
JS获取鼠标坐标并且根据鼠标位置不同弹出不同内容
2017/06/12 Javascript
Vue学习笔记进阶篇之vue-cli安装及介绍
2017/07/18 Javascript
微信小程序实现导航栏选项卡效果
2020/06/19 Javascript
详解Webpack loader 之 file-loader
2018/11/07 Javascript
10行代码实现微信小程序滑动tab切换
2018/12/28 Javascript
微信小程序基础教程之worker线程的使用方法
2019/07/15 Javascript
vue swipeCell滑动单元格(仿微信)的实现示例
2020/09/14 Javascript
[07:55]2014DOTA2 TI正赛第三日 VG上演推进荣耀DKEG告别
2014/07/21 DOTA
python使用sorted函数对列表进行排序的方法
2015/04/04 Python
numpy返回array中元素的index方法
2018/06/27 Python
详解Django+uwsgi+Nginx上线最佳实战
2019/03/14 Python
深入浅析python变量加逗号,的含义
2020/02/22 Python
Python爬虫:Request Payload和Form Data的简单区别说明
2020/04/30 Python
解决PyCharm IDE环境下,执行unittest不生成测试报告的问题
2020/09/03 Python
HTML5 audio标签使用js进行播放控制实例
2015/04/24 HTML / CSS
英国最大的体育&时尚零售公司:JD Sports
2017/12/13 全球购物
德国的大型美妆个护电商:Flaconi
2020/06/26 全球购物
物理力学求职信
2014/02/18 职场文书
反洗钱宣传活动总结
2014/08/26 职场文书
拾金不昧感谢信范文
2015/01/21 职场文书
幼师求职自荐信
2015/03/26 职场文书
MySQL 覆盖索引的优点
2021/05/19 MySQL
logback如何自定义日志存储
2021/08/30 Java/Android