基于Vue快速实现列表拖拽排序——draggable

写在前面

在业务中列表拖拽排序是比较常见的需求,常见的JS拖拽库有Sortable.js,Vue.Draggable等,大多数同学遇到这种需求也是更多的求助于这些JS库,其实,使用HTML原生的拖放事件来实现拖拽排序并不复杂,结合Vue的transition-group,还能快速的给排序添加过渡动画。

设置元素为可拖放

<div draggable="true">能被拖放的元素</div>

拖放事件

拖放涉及到两种元素,一种是被拖拽元素(源对象),一种是放置区元素(目标对象)。
按住A元素往B元素拖拽,A元素即为源对象,B元素即为目标对象

拖拽事件类型

触发对象事件名称说明
源对象dragstart源对象开始被拖动时触发
源对象drag源对象被拖动过程中反复触发
源对象dragend源对象拖动结束时触发=
目标对象dragenter源对象开始进入目标对象范围内触发
目标对象dragover源对象在目标对象范围内移动时触发
目标对象dragleave源对象离开目标对象范围时触发
目标对象drop源对象在目标对象范围内被释放时触发

拖拽排序

<template>
  <ul class="list">
    <li
      @dragenter="dragenter($event, index)"
      @dragover="dragover($event, index)"
      @dragstart="dragstart(index)"
      draggable
      v-for="(item, index) in list"
      :key="item.label"
      class="list-item"
     >
      {{item.label}}
    </li>
  </ul>
</template>
<script>
export default {
  data() {
    return {
      list: [
        { label: '列表1' },
        { label: '列表2' },
        { label: '列表3' },
        { label: '列表4' },
        { label: '列表5' },
        { label: '列表6' },
      ],
      dragIndex: '',
      enterIndex: '',
    };
  },
  methods: {
  // 源对象开始被拖动时触发
    dragstart(index) {
      this.dragIndex = index;
    },
    // 源对象开始进入目标对象范围内触发
    dragenter(e, index) {
      e.preventDefault();
      // 避免源对象触发自身的dragenter事件
      if (this.dragIndex !== index) {
        const source = this.list[this.dragIndex];
        this.list.splice(this.dragIndex, 1);
        this.list.splice(index, 0, source);
        // 排序变化后目标对象的索引变成源对象的索引
        this.dragIndex = index;
      }
    },
    // 源对象在目标对象范围内移动时触发
    dragover(e, index) {
      e.preventDefault();
    },
  },
};
</script>
<style lang="scss" scoped>
.list {
  list-style: none;
  .list-item {
    cursor: move;
    width: 300px;
    background: #EA6E59;
    border-radius: 4px;
    color: #FFF;
    margin-bottom: 6px;
    height: 50px;
    line-height: 50px;
    text-align: center;
  }
}
</style>

**当然这个拖拽效果有点生硬,下面使用Vue自带的transition-group组件,给排序添加平滑的过渡效果。
**

列表的排序过渡 (transition-group)

Vue的列表的: 排序过渡

<template>
  <div>
    <transition-group
      name="drag"
      class="list"
      tag="ul"
    >
      <li
        @dragenter="dragenter($event, index)"
        @dragover="dragover($event, index)"
        @dragstart="dragstart(index)"
        draggable
        v-for="(item, index) in list"
        :key="item.label"
        class="list-item">
        {{item.label}}
      </li>
    </transition-group>
  </div>
</template>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值