vue项目使用vue-draggable-plus对列表进行拖拽排序

4,850 阅读3分钟

vue-draggable-plus 是一个基于 SortableJS 的 Vue.js 插件,提供了更丰富的功能和更好的自定义选项,相比于 vue-draggable,它支持更多的定制化选项,如动画、拖拽方向、占位符、动态数据等。以下是 vue-draggable-plus 的详细使用教程,包括基本安装、配置、事件和高级功能的使用。

1. 安装 vue-draggable-plus

首先,安装 vue-draggable-plus 包:

npm install vue-draggable-plus --save

或者通过 Yarn 安装:

yarn add vue-draggable-plus

2. 基本使用

在 Vue 组件中使用 vue-draggable-plus 时,需要引入 Draggable 组件并配置数据源。最常见的用法是将 v-model 与数据绑定,类似于 Vue 的双向数据绑定,能够实现拖拽排序。

示例代码:

<template>
  <div>
    <draggable :list="items" @start="dragStarted" @end="dragEnded" group="items">
      <div v-for="item in items" :key="item.id" class="item">
        {{ item.name }}
      </div>
    </draggable>
  </div>
</template>

<script>
import Draggable from 'vue-draggable-plus';

export default {
  components: {
    Draggable
  },
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ]
    };
  },
  methods: {
    dragStarted(evt) {
      console.log('Drag started', evt);
    },
    dragEnded(evt) {
      console.log('Drag ended', evt);
    }
  }
};
</script>

<style scoped>
.item {
  padding: 10px;
  border: 1px solid #ccc;
  margin: 5px;
}
</style>

解释:

  • v-for 用于渲染每个项目,key 属性是为了确保每个项目是唯一的。
  • @start 和 @end 是拖拽开始和结束的事件。
  • :list 是用于绑定拖拽排序的数据源。
  • group 用来设置可拖拽的分组,避免不同列表之间的拖拽冲突。

3. 高级功能

3.1 自定义动画效果

你可以为拖拽添加动画效果,通过 draggable 组件的 moveset 属性进行自定义。例如,可以在拖拽过程中添加背景色变化、位移动画等。

<template>
  <draggable :list="items" :move="onMove" :set="onSet" group="items">
    <div v-for="item in items" :key="item.id" class="item">
      {{ item.name }}
    </div>
  </draggable>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ]
    };
  },
  methods: {
    onMove(evt) {
      // 你可以在这里定制拖拽时的动画效果
      return true; // 返回 true 表示允许移动
    },
    onSet(evt) {
      // 拖拽设置完成时触发
    }
  }
};
</script>

<style scoped>
.item {
  transition: all 0.3s ease;
}
</style>

3.2 拖拽限制

通过 draggable 组件的 handledisabled 属性,可以限制拖拽行为,例如只允许拖拽某些元素或禁用拖拽。

<template>
  <draggable :list="items" handle=".drag-handle" group="items">
    <div v-for="item in items" :key="item.id" class="item">
      <div class="drag-handle"></div> <!-- 拖动句柄 -->
      {{ item.name }}
    </div>
  </draggable>
</template>

<style scoped>
.drag-handle {
  cursor: move;
  display: inline-block;
  padding: 5px;
  background-color: #ddd;
}
</style>
  • handle 属性指定了允许拖拽的区域,其他地方点击则不能拖动。
  • disabled 属性可以禁用拖拽操作。

3.3 动态拖拽项

vue-draggable-plus 支持动态数据,即你可以通过 v-ifv-for 或外部数据改变排序时,拖拽项会自动更新。

<template>
  <div>
    <button @click="addItem">添加项目</button>
    <draggable :list="items" group="items">
      <div v-for="item in items" :key="item.id" class="item">
        {{ item.name }}
      </div>
    </draggable>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
      ]
    };
  },
  methods: {
    addItem() {
      const newId = this.items.length + 1;
      this.items.push({ id: newId, name: `Item ${newId}` });
    }
  }
};
</script>

每次点击按钮时,都会动态向列表中添加一个新的项,并且拖拽排序依然有效。

3.4 占位符与视觉效果

vue-draggable-plus 支持拖拽过程中显示占位符。当拖拽项被移动时,列表的空白位置会显示占位符,提示用户放置位置。

<template>
  <draggable :list="items" group="items" :ghost-class="'ghost'">
    <div v-for="item in items" :key="item.id" class="item">
      {{ item.name }}
    </div>
  </draggable>
</template>

<style scoped>
.item {
  padding: 10px;
  border: 1px solid #ccc;
  margin: 5px;
}

.ghost {
  background-color: rgba(0, 0, 0, 0.1);
}
</style>
  • ghost-class 用来设置拖拽时的视觉效果(例如改变背景色)。

3.5 支持多列拖拽

vue-draggable-plus 可以支持多列的拖拽排序,利用 group 属性来区分不同的拖拽组。

<template>
  <div class="container">
    <draggable :list="items" group="items" class="column" @end="onEnd">
      <div v-for="item in items" :key="item.id" class="item">
        {{ item.name }}
      </div>
    </draggable>
    <draggable :list="items2" group="items" class="column" @end="onEnd">
      <div v-for="item in items2" :key="item.id" class="item">
        {{ item.name }}
      </div>
    </draggable>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
      ],
      items2: [
        { id: 3, name: 'Item 3' },
        { id: 4, name: 'Item 4' },
      ]
    };
  },
  methods: {
    onEnd(evt) {
      console.log('Drag ended', evt);
    }
  }
};
</script>

<style scoped>
.container {
  display: flex;
  justify-content: space-between;
}
.column {
  width: 45%;
}
.item {
  padding: 10px;
  border: 1px solid #ccc;
  margin: 5px;
}
</style>