基于VUE的2种拖拽方式及其遇到的坑

2,394 阅读3分钟

1、与vue配套的拖拽组件vuedraggable

安装引入

安装  yarn add vuedraggable  或 npm install vuedraggable或 cnpm install vuedraggable
引入  import vuedraggable from 'vuedraggable';
连接引入
<script src="http://www.itxst.com/package/vue/vue.min.js"></script><script src="http://www.itxst.com/package/sortable/Sortable.min.js"></script><script src="http://www.itxst.com/package/vuedraggable/vuedraggable.umd.min.js"></script>
因为vuedraggable是基于Sortable做了vue处理的封装,所以必须先引入Sortable.min.js。
安装了vuedraggable可以直接使用Sortable.js,不用再安装。

例子

<template>
  <vuedraggable v-model="list">
    <transition-group>
      <div v-for="item in list" :key="item" class="item">
        <p>{{item}}</p>
      </div>
    </transition-group>
  </vuedraggable>
</template>

<script>
import vuedraggable from 'vuedraggable';
export default {
  name: 'HelloWorld',
  components: {vuedraggable},
  data() {
    return {
      list: [1,2,3,4,5,6]
    }
  },
</script>

<transition-group></transition-group> //用transition-group包裹起来会增加拖拽动画。

常用属性及说明

属性名称

说明

group

:group= "name",相同的组之间可以相互拖拽

sort

:sort= "true",是否开启内部排序,如果设置为false,它所在组无法排序,在其他组可以拖动排序

delay

:delay= "0", 鼠标按下后多久可以拖拽

touchStartThreshold

鼠标移动多少px才能拖动元素

disabled

:disabled= "true",是否启用拖拽组件

animation

拖动时的动画效果,还是很酷的,数字类型。如设置animation=1000表示1秒过渡动画效果

handle

:handle=".mover" 只有当鼠标移动到css为mover类的元素上才能拖动

filter

:filter=".unmover" 设置了unmover样式的元素不允许拖动

draggable

:draggable=".item" 那些元素是可以被拖动的

ghostClass

:ghostClass="ghostClass" 设置拖动元素的占位符类名,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true

chosenClass

:ghostClass="hostClass" 被选中目标的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true

dragClass

:dragClass="dragClass"拖动元素的样式,你的自定义样式可能需要加!important才能生效,并把forceFallback属性设置成true

dataIdAttr

dataIdAttr: 'data-id'

forceFallback

默认false,忽略HTML5的拖拽行为,因为h5里有个属性也是可以拖动,你要自定义ghostClass chosenClass dragClass样式时,建议forceFallback设置为true

fallbackClass

默认false,克隆的DOM元素的类名

allbackOnBody

默认false,克隆的元素添加到文档的body中

fallbackTolerance

拖拽之前应该移动的px

scroll

默认true,有滚动区域是否允许拖拽

scrollFn

滚动回调函数

scrollSensitivity

距离滚动区域多远时,滚动滚动条

scrollSpeed

滚动速度

优点:简单,不需要过多的配置,组件自带双向绑定。

唯一缺点,有一个业务需求,需要三列随意交换,使用element组件,发现嵌套在element ui内部拖拽无法使用,也可能是哪里配置出错了。我认为element UI与 vuedraggable 不兼容。

2、Sortable.js

为了完成上面的业务需求使用了Sortable.js插件解决需求。

安装引入

安装 npm/cnpm install sortablejs --save 或yarn add sortablejs --save引入 import Sortable from 'sortablejs';
连接引入 <script src="http://www.itxst.com/package/sortable/sortable.min.js"></script>

使用方式

 <ul calss="drag-parent" row-key="id">
       <li v-for="(item,index) in list" :key="item.index">
       <li/>
 <ul/>
//list 就省略了,有两点要注意
//1、父盒子要加row-key="id",不然会出现拖拽乱序,2、key的值不能是index,因为sortable 交换index值
不会交换,用index会出现乱序,必须用itm自带的唯一标识符。

sortVolunteer(){   //关键代码,行拖拽
        const that = this;
      this.$nextTick(()=>{
        const wrapperTr = document.querySelector('.drag-parent') //父盒子
        this.sortable = Sortable.create(wrapperTr, {
            animation: 180,
            delay: 0,
            // 开始拖拽的时候,行拖拽
            onEnd: ({newIndex,oldIndex}) => {
               let collegeIndex = this.index
              const targetRow = that.collegeList[collegeIndex].splice(oldIndex, 1)[0]   //collegeList[collegeIndex] 要交换的数组
              that.collegeList[collegeIndex].splice(newIndex, 0, targetRow)    
              const list = JSON.parse(JSON.stringify(this.collegeList));   // that.collegeList  绑定的总数组
              this.collegeList = [];
              this.$nextTick(()=>{
                    this.collegeList = list;
                    this.sortVolunteer(); // 为了解决element兼容问题这里必须在调用一次
//sortVolunteer 不然会出现乱序,不是element不用这些步骤。
                    });
            },
        })
              
          });
    },



列拖拽
      columnDrop() {
            if(this.sortable) this.sortable.destroy();
            this.$nextTick(()=>{
                const wrapperTr = document.querySelector('.tablewrap tr')
                this.sortable = Sortable.create(wrapperTr, {
                    animation: 180,
                    delay: 0,
                    filter:'.undragble',
                    group:{name:'shared',pull:true,put:true},
                    draggable:'.share',    //控制哪些列不可拖拽
                    // 开始拖拽的时候
                    onEnd: evt => {
                        const oldItem = this.col[evt.oldIndex];
                        this.col.splice(evt.oldIndex, 1);
                        this.col.splice(evt.newIndex, 0, oldItem);
                        const list = JSON.parse(JSON.stringify(this.list));   //深拷贝
                        this.list = [];   // that.list  绑定的总数组
                        this.$nextTick(()=>{
                            this.list = list;
                            this.columnDrop(); //重新执行一次
                        });
                    },
                })
                
            });
        },

Sortable优点是兼容所有的框架,例如jQuery,缺点是配置非常麻烦,而且sortVolunteer函数得自己写,里面的数据变化容易出错,建议优先使用vuedraggable。

Sortable 中文翻译网址www.sortablejs.com/ 具体配置项可以去参考。

如果排序使基于DOM层的,vuedraggable可能要失效,这时要使用sortable.js。