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 相关文章推荐
Javascript的各种节点操作实例演示代码
Jun 27 Javascript
JavaScript正则表达式中的ignoreCase属性使用详解
Jun 16 Javascript
javascript获取网页宽高方法汇总
Jul 19 Javascript
JS实现的表格操作类详解(添加,删除,排序,上移,下移)
Dec 22 Javascript
分享网页检测摇一摇实例代码
Jan 14 Javascript
JS中使用 after 伪类清除浮动实例
Mar 01 Javascript
js中DOM三级列表(代码分享)
Mar 20 Javascript
自适应布局meta标签中viewport、content、width、initial-scale、minimum-scale、maximum-scale总结
Aug 18 Javascript
webpack多入口文件页面打包配置详解
Jan 09 Javascript
Vue iview-admin框架二级菜单改为三级菜单的方法
Jul 03 Javascript
详解VUE里子组件如何获取父组件动态变化的值
Dec 26 Javascript
js 下拉菜单点击旁边收起实现(踩坑记)
Sep 29 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版微信公众账号第三方管理工具开发简明教程
2016/09/23 PHP
Yii框架实现图片上传的方法详解
2017/05/20 PHP
Laravel给生产环境添加监听事件(SQL日志监听)
2017/06/19 PHP
php压缩文件夹最新版
2018/07/18 PHP
html下载本地
2006/06/19 Javascript
jQuery对象[0]是什么含义?
2010/07/31 Javascript
无阻塞加载脚本分析[全]
2011/01/20 Javascript
图片延迟加载的实现代码(模仿懒惰)
2013/03/29 Javascript
谈谈JavaScript自定义回调函数
2015/10/18 Javascript
基于javascript实现漂亮的页面过渡动画效果附源码下载
2015/10/26 Javascript
基于javascript实现随机颜色变化效果
2016/01/14 Javascript
微信小程序 网络请求(post请求,get请求)
2017/01/17 Javascript
vue组件watch属性实例讲解
2017/11/07 Javascript
JavaScript实现的简单加密解密操作示例
2018/06/01 Javascript
浅谈vue websocket nodeJS 进行实时通信踩到的坑
2020/09/22 NodeJs
[31:00]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS iG
2014/05/25 DOTA
将Python中的数据存储到系统本地的简单方法
2015/04/11 Python
Python 12306抢火车票脚本 Python京东抢手机脚本
2018/02/06 Python
使用python实现快速搭建简易的FTP服务器
2018/09/12 Python
Django 实现购物车功能的示例代码
2018/10/08 Python
Python实现计算字符串中出现次数最多的字符示例
2019/01/21 Python
详解python的四种内置数据结构
2019/03/19 Python
如何使用Python 打印各种三角形
2019/06/28 Python
Django CBV与FBV原理及实例详解
2019/08/12 Python
自定义Django Form中choicefield下拉菜单选取数据库内容实例
2020/03/13 Python
Nisbets法国:英国最大的厨房和餐饮设备供应商
2019/03/18 全球购物
应届实习生的自我评价范文
2014/01/05 职场文书
售后服务经理岗位职责
2014/02/25 职场文书
优秀团员事迹材料2000字
2014/08/20 职场文书
锅炉工岗位职责
2015/02/13 职场文书
毕业设计致谢语
2015/05/14 职场文书
田径运动会通讯稿
2015/07/18 职场文书
导游词之沈阳清昭陵
2019/12/28 职场文书
浅谈python数据类型及其操作
2021/05/25 Python
Redis可视化客户端小结
2021/06/10 Redis
Python基础 括号()[]{}的详解
2021/11/07 Python