vuedraggable實際開發中的細節問題

原文地址vue

前言

公司項目中本來使用vue+jQuryUI實現拖拽的效果。本來實現方式也只是要它的拖拽動態效果,阻止默認的改變dom。經過事件對象獲取targetElement和toElement,就手動判斷接下來的數據操做邏輯。但jQueryUI相對臃腫。就需求換個輕量級的拖拽插件。git

插件選型:

先推薦個vue相關的插件庫
image
都嘗試了下,選擇了第一個基於sortablejs的vuedraggable。(star最多哈哈哈,配置項也最豐富)
這個插件使用方式很簡單。github

使用方式

注意要安裝兩個依賴
npm install vuedraggable sortable --save
用draggable包裹被拖拽的元素,options是拖拽效果行爲的相關配置,和sortable的配置基本徹底同樣,start end move是相關事件。vuex

<draggable v-model="myArray" :options="{group:'people'}" @start="drag" @end="drop" :move="checkMove">
   <div v-for="element in myArray">{{element.name}}</div>
</draggable>

.vue or .js 文件npm

import draggable from 'vuedraggable'
  ...
  export default {
        components: {
            draggable,
        },
        method:{
              drag : function(){
               ...
             }
              ...
        }       
}
  ...

遇到的問題

首先是拖拽的目標元素,由於被包裝後的事件對象只有index,對於更廣的使用場景來講就不太適用。例如目標元素的數據須要包裝加工,或者不須要顯示拖拽後的效果。vuedraggable介紹中與vuex一塊兒使用的方式,並未直接修改原有數據,而進行代理。canvas

computed: {
    myList: {
        get() {
            return this.$store.state.myList
        },
        set(value) {
            this.$store.commit('updateList', value)
        }
    }
}

雖然我司項目未使用vuex,但同理改造出以下代碼dom

computed: {
    xAxis: {
      get: function () {
        return this.dataConfig.xAxis;
         //return []  此時將不會沒有拖拽對象添加到對應元素中的效果。可是可獲取拖拽對象綁定的數據,
         //在目標元素中顯示canvas,圖表等等數據對應的組件
      },
      set: function (v) {
         //此處可對value進行修改,好比_.uniqBy,_.filter,或者限制長度Array.slice剪切
          ...
        this.$emit('updateDataColumn', {
          dataSourceCode: this.dataConfig.dataSourceCode,
          code: this.dataConfig.code,
          type: 'xAxis',
          columns: v
        });
      }
    }
}

PS:同時出現了個問題,使用的vuedraggable 2.13.1存在一個bug 拖入空元素中,當空元素的min-height大於第一個被拖拽進的元素時(必須對空元素設置min-height),會產生報錯Cannot read property 'map' of undefined。可是在2.14.1版本中獲得修復,相關issue可點擊查看佈局

第二個遇到的值得一提問題是關於HTML5原生拖拽和sortable本身實現的拖拽。默認爲原生拖拽。在拖拽到空元素,容器中生成新的組件的時候,空元素的結構和位置就出現了一些問題。空元素本來放在容器中,可是設置了min-height必然會影響頁面佈局。因而考慮到vuedraggable拖拽添加的具體行爲:拖拽通過目標空元素的時候,會先生成影子元素,除非在另外一個可落入區域drop的時候,都會添加到有影子元素的目標空元素。this

<draggable v-model="willAddToDataColumn" class="dragArea" :options="{group:'people'}" class="list-group list-group-right">
    <template v-for="item in willAddDataColumn">
    </template>
  </draggable>
  <draggable v-model="willAddDataColumn" class="dragArea" :options="{group:'people'}" class="list-group list-group-bottom">
    <template v-for="item in willAddToDataColumn">
    </template>
  </draggable>

分別絕對定位於容器的下,右邊,且右邊寬1px,下邊高1px。spa

.list-group{
  .sortable-chosen{display: none}  //不顯示影子元素。
  }
  .list-group-right{
    right: 0;
    position: absolute;
    height: 100%;
    width: 1px;
    top: 0;
  }
  .list-group-bottom{
    position: absolute;
    height: 1px;
    width: 100%;
    bottom: 0;
    margin-bottom: 0;
  }

實現卻是能實現了。可是在容器中卻出現了鼠標變爲不可落入狀態的顯示bug。因而查看sortable配置的文檔。發現可經過設置forceFallback:true, fallbackClass:'draggingStyle'來禁止使用HTML5原生拖拽。轉而使用可自定義樣式的拖拽。實際操做過程用又發現以前的拖拽添加的具體行爲發生了改變。無法添加進去了。囧。
最終仍是找了HTML5原生拖拽來fix,在容器中添加
<div class='container' @dragover="allowDrop">...</div>

allowDrop:function (ev) {
          ev.preventDefault();
        }

以上

相關文章
相關標籤/搜索