探讨把一个元素从它所在的div 拖动到另一个div内的实现方法

栏目: jQuery · 发布时间: 7年前

内容简介:接到一个新需求,要求用vue搞,主要是拖动实现布局,关键点有H5拖动的缺点:不能限制在水平 或垂直方向上拖动。使用原生js缺点:大量的dom操作,代码复杂(jquery ui 封装的比较好了,可直接用)

故事背景:

接到一个新需求,要求用vue搞,主要是拖动实现布局,关键点有 : 单个组件拖动,一行多列里面的组件拖动,  单个组件可以拖入一行多列里 , 单个组件的拖动好实现,关键是把一个组件拖动到另一个类似于表格里面,而且有的情况下还需要限制 拖动只能在水平方向 ,自己搜集资料, 实验,终于搞出来了。

原理上主要分为两类:

  1. HTML5自带的拖放api,可用的库有 :  Vue.Draggable   
  2. 使用js 监听鼠标的移动位置, 可用的库有:  jquery ui
  3. 使用point-event: none(下面会详细说明)

各自缺点

H5拖动的缺点:不能限制在水平 或垂直方向上拖动。

使用原生js缺点:大量的dom操作,代码复杂(jquery ui 封装的比较好了,可直接用)

但是问题来了,这次的需求是把基于jquery ui 的拖动 用 vue 重构,那么用vue.draggable吧, 但是需求里正好有一条是要限制在水平方向上拖动,尴尬,用不了。

寻找方案

最开始的尝试:

<!DOCTYPE html>
<html>
<head>
	<title>vue结合原生js实现拖动</title>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<div class="ctn ctn1">
	<div class="sub sub1" v-for="(site, index) in list1">
   	  <div class="dragCtn fixed" :style="{ left: X+'px', top: Y+'px'}"
           @mousedown="mousedown(site, $event)"
           @mousemove.prevent='mousemove(site, $event)'
           @mouseup='mouseup(site, $event)'>
   	  	拖动我
   	  </div>
   </div>
</div>

<div class="ctn ctn2">
	<div class="sub sub2" v-for="(site, index) in list2"
          @mouseenter='mouseenter(site, $event)'>
   	  <div class="dragCtn">
   	  	{{ index }} : {{ site.name }}
   	  </div>
   </div>
</div>
   
</div>

<script>
new Vue({
  el: '#app',
  data: {
    list1: [{name:1, index:0}],
    list2: [{name:'a', index:0}, {name:'b', index:1}, {name:'c', index: 2}, {name:'d', index: 3}],
    vm:'',
    sb_bkx: 0,
    sb_bky: 0,
    is_moving: false,
    X: 0,
    Y: 0
  },
  methods: {
  	mousedown: function (site, event) {
		var startx=event.x;
		var starty=event.y;
		this.sb_bkx=startx - event.target.offsetLeft;
		this.sb_bky=starty - event.target.offsetTop;
		this.is_moving = true;
  	},
  	mousemove: function (site, event) {
  		var endx=event.x - this.sb_bkx;
		  var endy=event.y - this.sb_bky;
		  var _this = this
		  if(this.is_moving){
	    	this.X = endx;
	    	this.Y = endy;
      }
  	},
  	mouseup: function (e) {
  	  this.is_moving = false;
  	},
    mouseenter: function (){
      console.log('鼠标进入')
    }
  }
})
</script>

<style>
    .ctn{
    	line-height: 50px;
    	cursor: pointer;
    	font-size: 20px;
    	text-align: center;
    	float: left;
    }
    .sub:hover{
        background: #e6dcdc;
        color: white;
        width: 100px;
    }
   	.ctn1{
   		border: 1px solid green;
   		width: 100px;
   	}
   	.ctn2{
   		border: 1px solid black;
   		width: 100px;
   		margin-left: 50px;
   	}
   	.fixed{
   	  width: 100px;
      position: fixed;
      background: red;
      left: 0;
      top: 0;
      cursor: move;
   	}
</style>
</body>
</html>
复制代码

就这样实现了基本的拖动,但是在拖动的时候,就不能触 mouseenter   事件了,而且鼠标必须拖动的很慢,移动快一点,拖动的div就跟不上了,这一点到现在还困惑,希望各位大侠指点。然后在网上找了很多资料,类库,但是不能完全符合我的需求,于是准备自己写了;

首先是给组件添加mousedown事件,然后mousemove的时候 监听鼠标的位置,再赋值给组件,实现拖动,但是当组件拖动进入另一个元素的时候,无法监听mouseenter, 后来想的办法是给正在拖动的组件加上 point-event:none 属性,就是消除原有的鼠标事件,就可以触发其他组件的mouerenter事件了,point-event 属性的具体用法 可以参考这里:

www.zhangxinxu.com/wordpress/2…

因为拖动是用原生js写的,所以可以限制在水平方向拖动,再加上可以触发mouseenter事件,就正好实现的我的需求。

伪代码如下:

mousedown: function (event, site) {        document.onmousemove=function (ev) {          // 移动的时候给元素增加 point-event:none 属性           
           ...        }        document.onmouseup=function (ev) {
           // up的时候 要移除point-event属性
           ...         }    }复制代码

但是后来上面要求,要兼容ie10,由于  point-event:none 是H5的属性,于是我赶紧去看看兼容性, 可怕的事发生了, point-event 属性只兼容到 ie11 ,完蛋!

再想其他办法吧,没了思路,老版本的拖动是基于 jquery ui  的 ,于是去看了 jquery ui 的源码,看看它的拖动是怎么实现的。

jquery ui 拖动实现原理

不熟悉 jquery ui 的拖动方法的可以先看下 这里

看下面这段代码:

$(function() {
    $( "#draggable" ).draggable();
    $( "#droppable" ).droppable({
      drop: function( event, ui ) {
        $( this ).html( "Dropped!" );
      }
    });
  });复制代码

之前的关键问题就是怎么判断拖动的元素 $( "#draggable" )  在什么时候 进入了可以放置的区域       $( "#droppable" )  的,看了源码,它的实现方式 简单来说就是拖动   $( "#draggable" )  的时候监听 鼠标的位置, 同时获取   $( "#droppable" ) 的区域位置信息,只要鼠标进入该区域,就触发。

顺着这个思路,做了实验 可以满足自己的需求 good !

demo的实现效果如下:

探讨把一个元素从它所在的div 拖动到另一个div内的实现方法

代码地址:  https://github.com/YalongYan/vue-drag-layout

拖动布局的实现方式应该还有更好的,欢迎大家提出更好的实现方式。


以上所述就是小编给大家介绍的《探讨把一个元素从它所在的div 拖动到另一个div内的实现方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

Making Things See

Making Things See

Greg Borenstein / Make / 2012-2-3 / USD 39.99

Welcome to the Vision Revolution. With Microsoft's Kinect leading the way, you can now use 3D computer vision technology to build digital 3D models of people and objects that you can manipulate with g......一起来看看 《Making Things See》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具