当前位置:首页 > VUE

Vue拖拽怎么实现

2026-02-18 12:44:07VUE

Vue 拖拽实现方法

使用 HTML5 原生拖拽 API

HTML5 提供了原生拖拽 API,可以通过 draggable 属性和相关事件实现拖拽功能。

<template>
  <div 
    draggable="true"
    @dragstart="handleDragStart"
    @dragend="handleDragEnd"
    @dragover.prevent
    @drop="handleDrop"
  >
    拖拽元素
  </div>
</template>

<script>
export default {
  methods: {
    handleDragStart(e) {
      e.dataTransfer.setData('text/plain', e.target.id);
    },
    handleDrop(e) {
      const data = e.dataTransfer.getData('text/plain');
      const draggedElement = document.getElementById(data);
      e.target.appendChild(draggedElement);
    }
  }
}
</script>

使用第三方库 vue-draggable

vue-draggable 是基于 Sortable.js 的 Vue 拖拽组件,适合列表排序等场景。

安装:

Vue拖拽怎么实现

npm install vuedraggable

使用:

<template>
  <draggable v-model="list" @end="onDragEnd">
    <div v-for="item in list" :key="item.id">
      {{ item.name }}
    </div>
  </draggable>
</template>

<script>
import draggable from 'vuedraggable';

export default {
  components: { draggable },
  data() {
    return {
      list: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' }
      ]
    };
  },
  methods: {
    onDragEnd() {
      console.log('拖拽结束');
    }
  }
}
</script>

使用自定义指令实现拖拽

可以通过 Vue 自定义指令实现更灵活的拖拽控制。

Vue拖拽怎么实现

<template>
  <div v-draggable class="drag-item">可拖拽元素</div>
</template>

<script>
export default {
  directives: {
    draggable: {
      inserted(el) {
        el.draggable = true;
        el.style.cursor = 'move';

        el.addEventListener('dragstart', (e) => {
          e.dataTransfer.setData('text/plain', el.id);
          el.classList.add('dragging');
        });

        el.addEventListener('dragend', () => {
          el.classList.remove('dragging');
        });
      }
    }
  }
}
</script>

<style>
.dragging {
  opacity: 0.5;
}
</style>

拖拽与动画结合

可以结合 Vue 的过渡动画实现更流畅的拖拽效果。

<template>
  <transition-group name="list" tag="div">
    <div 
      v-for="item in items" 
      :key="item.id"
      draggable="true"
      @dragstart="dragStart(item)"
      @dragover.prevent
      @drop="drop(item)"
    >
      {{ item.text }}
    </div>
  </transition-group>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, text: 'Item 1' },
        { id: 2, text: 'Item 2' }
      ],
      draggedItem: null
    };
  },
  methods: {
    dragStart(item) {
      this.draggedItem = item;
    },
    drop(item) {
      const draggedIndex = this.items.indexOf(this.draggedItem);
      const dropIndex = this.items.indexOf(item);
      this.items.splice(draggedIndex, 1);
      this.items.splice(dropIndex, 0, this.draggedItem);
    }
  }
}
</script>

<style>
.list-item {
  transition: all 0.5s;
}
.list-enter-active, .list-leave-active {
  transition: all 0.5s;
}
.list-enter, .list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
</style>

拖拽边界限制

可以通过计算位置限制拖拽范围。

<template>
  <div 
    ref="dragElement"
    class="drag-box"
    @mousedown="startDrag"
    @mousemove="onDrag"
    @mouseup="stopDrag"
    @mouseleave="stopDrag"
  >
    可拖拽区域
  </div>
</template>

<script>
export default {
  data() {
    return {
      isDragging: false,
      startX: 0,
      startY: 0,
      offsetX: 0,
      offsetY: 0
    };
  },
  methods: {
    startDrag(e) {
      this.isDragging = true;
      this.startX = e.clientX;
      this.startY = e.clientY;
      const rect = this.$refs.dragElement.getBoundingClientRect();
      this.offsetX = this.startX - rect.left;
      this.offsetY = this.startY - rect.top;
    },
    onDrag(e) {
      if (!this.isDragging) return;
      const x = e.clientX - this.offsetX;
      const y = e.clientY - this.offsetY;

      // 限制在视口范围内
      const maxX = window.innerWidth - this.$refs.dragElement.offsetWidth;
      const maxY = window.innerHeight - this.$refs.dragElement.offsetHeight;

      this.$refs.dragElement.style.left = `${Math.min(Math.max(0, x), maxX)}px`;
      this.$refs.dragElement.style.top = `${Math.min(Math.max(0, y), maxY)}px`;
    },
    stopDrag() {
      this.isDragging = false;
    }
  },
  mounted() {
    this.$refs.dragElement.style.position = 'absolute';
  }
}
</script>

<style>
.drag-box {
  width: 100px;
  height: 100px;
  background: #42b983;
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: move;
}
</style>

这些方法涵盖了从简单到复杂的 Vue 拖拽实现方案,可以根据具体需求选择合适的实现方式。

标签: 拖拽Vue
分享给朋友:

相关文章

vue实现拖拽计算器

vue实现拖拽计算器

Vue实现拖拽计算器的步骤 创建Vue项目 使用Vue CLI创建一个新项目,确保已安装Vue和必要的依赖项。通过命令行初始化项目并安装依赖。 vue create drag-calculator…

vue实现拖拽到容器里

vue实现拖拽到容器里

实现拖拽到容器的基本步骤 安装并引入 Vue.Draggable 库,这是一个基于 Sortable.js 的 Vue 拖拽组件。可以通过 npm 或 yarn 进行安装。 npm install…

Vue实现闯关

Vue实现闯关

Vue 实现闯关功能的方法 使用 Vue 实现闯关功能通常需要结合组件化开发、状态管理和动画效果。以下是实现闯关功能的几种方法: 组件化设计 将闯关界面拆分为多个组件,如关卡选择组件、游戏主界面组…

Vue数据依赖实现

Vue数据依赖实现

Vue数据依赖实现原理 Vue的数据依赖实现基于响应式系统,核心是通过Object.defineProperty或Proxy拦截数据变化,结合发布-订阅模式实现依赖收集和更新触发。 核心机制 依赖收…

vue实现拖拽连接

vue实现拖拽连接

Vue 实现拖拽连接功能 在 Vue 中实现拖拽连接功能通常涉及使用 HTML5 的拖放 API 或第三方库(如 vuedraggable)。以下是两种常见实现方式: 使用 HTML5 拖放 AP…

vue实现carousel拖拽

vue实现carousel拖拽

实现拖拽轮播的基本思路 在Vue中实现可拖拽的Carousel组件需要结合触摸事件(touchstart、touchmove、touchend)和鼠标事件(mousedown、mousemove、mo…