前言
公司项目中原本使用vue+jQuryUI实现拖拽的效果。原本实现方式也只是要它的拖拽动态效果,阻止默认的改变dom。通过事件对象获取targetElement和toElement,就手动判断接下来的数据操作逻辑。但jQueryUI相对臃肿。就需求换个轻量级的拖拽插件。
插件选型:
先推荐个vue相关的插件库
都尝试了下,选择了第一个基于sortablejs的vuedraggable。(star最多哈哈哈,配置项也最丰富)
这个插件使用方式很简单。
使用方式
注意要安装两个依赖npm install vuedraggable sortable --save
用draggable包裹被拖拽的元素,options是拖拽效果行为的相关配置,和sortable的配置基本完全一样,start end move是相关事件。
<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 文件
import draggable from 'vuedraggable'
...
export default {
components: {
draggable,
},
method:{
drag : function(){
...
}
...
}
}
...
遇到的问题
首先是拖拽的目标元素,因为被包装后的事件对象只有index,对于更广的使用场景来说就不太适用。例如目标元素的数据需要包装加工,或者不需要显示拖拽后的效果。vuedraggable介绍中与vuex一起使用的方式,并未直接修改原有数据,而进行代理。
computed: {
myList: {
get() {
return this.$store.state.myList
},
set(value) {
this.$store.commit('updateList', value)
}
}
}
虽然我司项目未使用vuex,但同理改造出如下代码
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的时候,都会添加到有影子元素的目标空元素。
<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。
.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();
}
以上
所有评论(0)