内容简介:接到一个新需求,要求用vue搞,主要是拖动实现布局,关键点有H5拖动的缺点:不能限制在水平 或垂直方向上拖动。使用原生js缺点:大量的dom操作,代码复杂(jquery ui 封装的比较好了,可直接用)
故事背景:
接到一个新需求,要求用vue搞,主要是拖动实现布局,关键点有 : 单个组件拖动,一行多列里面的组件拖动, 单个组件可以拖入一行多列里 , 单个组件的拖动好实现,关键是把一个组件拖动到另一个类似于表格里面,而且有的情况下还需要限制 拖动只能在水平方向 ,自己搜集资料, 实验,终于搞出来了。
原理上主要分为两类:
- HTML5自带的拖放api,可用的库有 : Vue.Draggable
- 使用js 监听鼠标的移动位置, 可用的库有: jquery ui
- 使用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的实现效果如下:
代码地址: https://github.com/YalongYan/vue-drag-layout
拖动布局的实现方式应该还有更好的,欢迎大家提出更好的实现方式。
以上所述就是小编给大家介绍的《探讨把一个元素从它所在的div 拖动到另一个div内的实现方法》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 使用RxJava实现ImageView的拖动、旋转和缩放
- Testing Flutter apps翻译-点击,拖动和输入文本
- ios – 我正在使用XCode 7和Swift,我的控制拖动动作不起作用
- CSS 基础:块级元素、行内元素、替换元素、非替换元素
- CSS 技巧篇(六):display设置元素为行内元素时,元素之间存在间隙问题
- 探究行内元素和块级元素
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。