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();
        }

以上

相关文章
相关标签/搜索