这一篇文章引入vue.draggable拖拽列表他,有动画效果更流畅。

vue.draggable官网

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>vue.draggable拖拽列表,更换元素位置</title>
  <!--引入 element-ui 的样式,-->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <script src="https://cdn.bootcss.com/vue/2.5.16/vue.min.js"></script>
  <!-- 引入element 的组件库-->
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="https://www.itxst.com/package/sortable/Sortable.min.js"></script>
  <script src="https://www.itxst.com/package/vuedraggable/vuedraggable.umd.min.js"></script>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    #app {
      margin: 50px;
    }


    .item {
      padding: 8px 12px;
      border-radius: 3px;
      transition: background-color 0.3s;
      margin-bottom: 4px;
      position: relative;
      border: 1px solid #000;
      background-color: #fff;
    }

    .item .add {
      display: none;
      justify-content: center;
      align-items: center;
      position: absolute;
      font-size: 18px;
      color: #2c66ff;
      border-radius: 50%;
      left: -10px;
      top: 30%;
    }

    .item .icon {
      color: red;
      font-size: 30px;
      cursor: pointer;
      margin-bottom: 10px;
    }

    /* 拖拽时候的样式 */
    .item.chosen {
      background: #fff;
      filter: drop-shadow(0px 8px 24px rgba(18, 19, 20, 0.18));
    }
    .item.chosen .add {
      display: block;
    }


    /* 拖拽到哪里的样式 */
    .item.ghost {
      position: relative;
      border-top-color: #2c66ff;
    }
    .item.ghost .add {
      display: none;
    }
  </style>
</head>

<body>
  <div id="app">
    <!-- chosen-class写法要规范,如果写chosenClass对应的class会识别不了 -->
    <draggable v-model="summaryArr" force-fallback="true" group="id" animation="300" @start="onStartDraggable"
      @end="onEndDraggable" handle=".drag-wrap" chosen-class="chosen" ghost-class="ghost">
      <transition-group>
        <div v-for="(item, index) in summaryArr" :key="index" class="item">
          <i class="add el-icon-circle-plus-outline"></i>
          <div class="icon-wrap" @click.stop>
            <!-- 拖拽icon -->
            <i class="icon el-icon-rank drag-wrap"></i>
          </div>
          <div class="item-con">{{item.text}}</div>
        </div>
      </transition-group>
    </draggable>
  </div>
  <script>
    new Vue({
      el: '#app',
      data() {
        return {
          // 源数据
          summaryArr: [
            {
              id: '1',
              text: '内容1'
            },
            {
              id: '2',
              text: '内容2'
            },
            {
              id: '3',
              text: '内容3'
            },
            {
              id: '4',
              text: '内容4'
            },
            {
              id: '5',
              text: '内容5'
            }
          ],
          // 深拷贝源数据
          summaryArrCopy: [],
          // 拖拽
          drag: false,
        }
      },
      created() {
        // 深拷贝最新的源数据,目的是为了判断拖拽的位置是否有没有更换,没有更换就不调接口
        this.summaryArrCopy = JSON.parse(JSON.stringify(this.summaryArr));
      },
      methods: {
        // 开始拖拽
        onStartDraggable() {
          this.drag = true;
        },
        // 拖拽完毕,调取接口
        async onEndDraggable() {
          // 是否更换过位置,如果拖拽过后还是原位置,则不掉接口
          const isChangePosition = this.summaryArr.some((item, index) => {
            if (item.id === this.summaryArrCopy[index].id) {
              return false;
            } else {
              return true;
            }
          });
          this.drag = false;
          if (isChangePosition) {
            // 深拷贝最新的源数据,目的是为了判断拖拽的位置是否有没有更换,没有更换就不调接口
            this.summaryArrCopy = JSON.parse(JSON.stringify(this.summaryArr));
            // 调取接口
            console.log(this.summaryArr, '排序过后的数据')
            this.$message({
              message: '排序成功!',
              type: 'success'
            });
          }
        },

      }
    })
  </script>

</body>

</html>

注意事项:

1.drag-wrap放在哪个元素上则该元素会有拖拽功能,我这个demo是放在了拖拽的icon上面,需要更大的拖拽范围可以放在item上面。
2.在标签上的自定义属性需要用“-”分割,不要用驼峰。需要这样写:chosen-class="chosen",不能用chosenClass="chosen",如果写chosenClass对应的class会识别不了


我的一个道姑朋友
80 声望4 粉丝

星光不问赶路人,岁月不负有心人。