探討把一個元素從它所在的div 拖動到另外一個div...

故事背景:css

接到一個新需求,要求用vue搞,主要是拖動實現佈局,關鍵點有:單個組件拖動,一行多列裏面的組件拖動,  單個組件能夠拖入一行多列裏, 單個組件的拖動好實現,關鍵是把一個組件拖動到另外一個相似於表格裏面,並且有的狀況下還須要限制拖動只能在水平方向,本身蒐集資料, 實驗,終於搞出來了。

原理上主要分爲兩類:
HTML5自帶的拖放api,可用的庫有 : Vue.Draggable
使用js 監聽鼠標的移動位置, 可用的庫有: jquery ui
使用point-event: none(下面會詳細說明)
各自缺點
H5拖動的缺點:不能限制在水平 或垂直方向上拖動。html

使用原生js缺點:大量的dom操做,代碼複雜(jquery ui 封裝的比較好了,可直接用)vue

可是問題來了,此次的需求是把基於jquery ui 的拖動 用 vue 重構,那麼用vue.draggable吧, 可是需求里正好有一條是要限制在水平方向上拖動,尷尬,用不了。jquery

尋找方案
最開始的嘗試:git

[HTML] 純文本查看 複製代碼
?github

<!DOCTYPE html>
<html>
<head>api

<title>vue結合原生js實現拖動</title>

<script src="https://cdn.bootcss.com/vue/2...;></script>
</head>
<body>
<div id="app">
<div class="ctn ctn1">app

<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>dom

<div class="ctn ctn2">wordpress

<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事件,就正好實現的個人需求。

僞代碼以下:

[JavaScript] 純文本查看 複製代碼
?

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 的拖動方法的能夠先看下  這裏   

  看下面這段代碼:

[JavaScript] 純文本查看 複製代碼
?

$(function() {

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

});

以前的關鍵問題就是怎麼判斷拖動的元素  $( "#draggable" )  在何時 進入了能夠放置的區域      $( "#droppable" ) 的,看了源碼,它的實現方式 簡單來講就是拖動  $( "#draggable" )  的時候監聽 鼠標的位置, 同時獲取  $( "#droppable" )   的區域位置信息,只要鼠標進入該區域,就觸發。

  順着這個思路,作了實驗 能夠知足本身的需求 good !

  demo的實現效果以下:

代碼地址: https://github.com/YalongYan/...

拖動佈局的實現方式應該還有更好的,歡迎你們提出更好的實現方式。更多技術資訊可關注:gzitcast

相關文章
相關標籤/搜索