vuedraggable拖拽

802 阅读2分钟

一、基本使用(列表拖拽和表格拖拽)

1、效果

动图.gif

2、下载插件

    npm i vuedraggable   // 2.24.3

3、使用

<template>
  <div class="draggable">
    <button @click="disabled = !disabled">{{disabled?'启用拖拽':'禁用拖拽'}}</button>
    <h1>列表拖拽</h1>
    <div>{{drag?'拖拽中':'拖拽停止'}}</div>
    <Draggable tag='ul' v-model="list" :disabled="disabled" animation="300" @start="handleStart" @end="handleEnd" chosen-class="chosen">
      <li v-for="(item,index) of list" :key="index">{{item}}</li>
    </Draggable>
    <h1>表格拖拽</h1>
    <div>{{drag?'拖拽中':'拖拽停止'}}</div>
    <Draggable tag='table' v-model="list" :disabled="disabled" animation="300" @start="handleStart" @end="handleEnd">
      <tr v-for="(item,index) of list" :key="index">
        <td>{{index}}</td>
        <td>{{item}}</td>
      </tr>
    </Draggable>
  </div>
</template>
<script>
import Draggable from 'vuedraggable'
export default {
  data() {
    return {
      disabled: false,
      drag: false,
      list: ['张三', '李四', '王五', '赵六']
    }
  },
  methods: {
    //开始拖拽事件
    handleStart() {
      this.drag = true
    },
    //拖拽结束事件
    handleEnd() {
      this.drag = false
      console.log('handleEnd', this.list)
    }
  },
  components: { Draggable }
}
</script>
<style lang='less' scoped>
.draggable {
  padding: 10px;
  > ul {
    li {
      background-color: greenyellow;
      user-select: none;
      line-height: 30px;
      &:hover {
        background-color: yellowgreen;
        cursor: move;
      }
      + li {
        margin-top: 10px;
      }
      &.chosen {
        border: solid 2px skyblue;
      }
    }
  }
  > table {
    border-collapse: collapse;
    tr {
      td {
        width: 100px;
        line-height: 30px;
        background-color: greenyellow;
        border: 1px solid #ccc;
      }
    }
  }
}
</style>

二、多列拖拽

1、效果

动图.gif

2、代码

<template>
  <div class="draggable">
    <h1>多列拖拽</h1>
    <div>{{warning}}</div>
    <div class="line-wrapper">
      <Draggable tag='ul' v-model="list" :group="groupA" animation="300">
        <li v-for="(item,index) of list" :key="index">{{item}}</li>
      </Draggable>
      <Draggable tag='ul' v-model="list1" :group="groupB" animation="300">
        <li v-for="(item,index) of list1" :key="index">{{item}}</li>
      </Draggable>
    </div>
  </div>
</template>
<script>
import Draggable from 'vuedraggable'
export default {
  data() {
    return {
      drag: false,
      list: ['张三', '李四', '王五', '赵六'],
      list1: ['罗翔'],
      groupA: {
        name: 'site',
        pull: true, // 是否允许拖出当前组,默认为true
        put: true // 是否允许拖入当前组,默认为true
      },
      groupB: { name: 'site', pull: () => this.list1.length > 2 }
    }
  },
  computed: {
    warning(vm) {
      return vm.list1.length <= 2 ? '不能再拖出了' : ''
    }
  },
  components: { Draggable }
}
</script>
<style lang='less' scoped>
.draggable {
  padding: 10px;
  .line-wrapper {
    display: flex;
    > ul {
      flex: 0.5;
      border: 2px solid pink;
      li {
        background-color: greenyellow;
        user-select: none;
        line-height: 30px;
        &:hover {
          background-color: yellowgreen;
          cursor: move;
        }
        + li {
          margin-top: 10px;
        }
        &.chosen {
          border: solid 2px skyblue;
        }
      }
    }
  }
}
</style>

3、实现多列拖拽的属性

当两个Draggable组件传入group属性时,值为同一个,例如group='site',那么这两个组件可以实现相互之间的拖拽

或者传入:group='groupA':group='groupB',设置name值为同一个,也可以实现相互之前的拖拽。对象形式传入时,pullput默认都是true,可以设置为布尔值或者一个函数

三、其他属性

1、delay="100"

鼠标按下后100ms后才能拖拽,防止误操作。默认为0

2、animation="300"

设置动画时间。默认为0

3、handle=".mover"

指定可以进行拖拽的元素类名。默认为空,mover为自定义的类名

      <Draggable tag='ul' v-model="list" animation="300" handle=".mover">
        <li v-for="(item,index) of list" :key="index">
          <el-button class="mover">+</el-button>
          {{item}}
        </li>
      </Draggable>

el-button标签为可拖拽元素

4、filter=".forbid"

指定不可以被拖拽的元素类名。默认为空,forbid为自定义的类名

      <Draggable tag='ul' v-model="list" animation="300" handle=".mover" filter=".forbid">
        <li v-for="(item,index) of list" :key="index">
          <el-button class="mover" :class="{forbid:index===0}">+</el-button>
          {{item}}
        </li>
      </Draggable>

index为0的元素不能被拖拽

5、:move="handleMove"

当拖拽时,获取到当前事件对象:

image.png 从中可以拿到目标对象,可以做出判断,禁止拖拽到此目标

filter=".forbid"结合便可以达到禁止此项拖拽,并且禁止别的项拖拽到此项的位置上。注意:需要被禁止的项一般要放到列表的最前面或最后面

      <Draggable tag='ul' v-model="list" :group="groupA" animation="300" filter=".forbid" :move='handleMove'>
        <li :class="{forbid:item==='王五'}" v-for="(item,index) of list" :key="index">{{item}}</li>
      </Draggable>
      
    handleMove(e) {
      console.log(e, e.relatedContext.element)
      return e.relatedContext.element !== '王五'
    }

6、chosen-class ghost-class 自定义鼠标按下和拖拽时的类名

默认的类名为sortable-chosen(鼠标按下)、sortable-ghost(鼠标拖拽) image.png 可以通过chosen-class ghost-class自定义 image.png

7、拷贝拖拽

通过pull: 'clone'实现拷贝拖拽

    <Draggable tag='ul' v-model="list" :group='groupA' animation="300" :move="handleMove">
      <li v-for="item of list" :key="item.id">{{item.name}}</li>
    </Draggable>
    <Draggable tag='ul' v-model="arr2" group="site" animation="300">
      <li v-for="item of arr2" :key="item.id">{{item.name}}</li>
    </Draggable>
    
    
  data() {
    return {
      list: [
        { id: 1, name: 'www.itxst.com' },
        { id: 2, name: 'www.jd.com' },
        { id: 3, name: 'www.baidu.com' },
        { id: 4, name: 'www.taobao.com' },
        { id: 5, name: 'www.google.com' }
      ],
      arr2: [{ id: 11, name: '常用菜单' }],
      groupA: { name: 'site', pull: 'clone' }
    }
  }, 
  methods: {
    handleMove(e) {
      const draggedId = e.draggedContext.element.id
      if (this.arr2.map((item) => item.id).includes(draggedId)) return false
    }
  }

8、事件列表

image.png