当前位置:首页 > VUE

vue实现弹窗拖拽排序

2026-02-25 05:30:50VUE

Vue 实现弹窗拖拽排序

使用 Vue.Draggable 库

安装 Vue.Draggable 库:

npm install vuedraggable

在组件中引入并使用:

<template>
  <div>
    <draggable v-model="dialogList" @end="onDragEnd">
      <div v-for="dialog in dialogList" :key="dialog.id" class="dialog-item">
        {{ dialog.title }}
      </div>
    </draggable>
  </div>
</template>

<script>
import draggable from 'vuedraggable'

export default {
  components: { draggable },
  data() {
    return {
      dialogList: [
        { id: 1, title: 'Dialog 1' },
        { id: 2, title: 'Dialog 2' },
        { id: 3, title: 'Dialog 3' }
      ]
    }
  },
  methods: {
    onDragEnd() {
      console.log('New order:', this.dialogList)
    }
  }
}
</script>

<style>
.dialog-item {
  padding: 10px;
  margin: 5px;
  background: #f0f0f0;
  cursor: move;
}
</style>

自定义拖拽实现

通过 HTML5 的拖放 API 实现:

<template>
  <div>
    <div
      v-for="dialog in dialogList"
      :key="dialog.id"
      class="dialog-item"
      draggable="true"
      @dragstart="handleDragStart($event, dialog.id)"
      @dragover.prevent
      @drop="handleDrop($event, dialog.id)"
    >
      {{ dialog.title }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialogList: [
        { id: 1, title: 'Dialog 1' },
        { id: 2, title: 'Dialog 2' },
        { id: 3, title: 'Dialog 3' }
      ],
      draggedItemId: null
    }
  },
  methods: {
    handleDragStart(event, id) {
      this.draggedItemId = id
      event.dataTransfer.effectAllowed = 'move'
    },
    handleDrop(event, targetId) {
      const draggedIndex = this.dialogList.findIndex(item => item.id === this.draggedItemId)
      const targetIndex = this.dialogList.findIndex(item => item.id === targetId)

      if (draggedIndex !== -1 && targetIndex !== -1) {
        const newList = [...this.dialogList]
        const [removed] = newList.splice(draggedIndex, 1)
        newList.splice(targetIndex, 0, removed)
        this.dialogList = newList
      }
    }
  }
}
</script>

结合弹窗组件实现

在弹窗组件中添加拖拽功能:

<template>
  <div>
    <button @click="showDialog = true">Show Dialog</button>

    <div v-if="showDialog" class="dialog-wrapper" ref="dialog">
      <div class="dialog-header" @mousedown="startDrag">
        Drag Me
        <button @click="showDialog = false">Close</button>
      </div>
      <div class="dialog-content">
        Dialog Content
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showDialog: false,
      isDragging: false,
      startX: 0,
      startY: 0,
      startLeft: 0,
      startTop: 0
    }
  },
  methods: {
    startDrag(e) {
      this.isDragging = true
      this.startX = e.clientX
      this.startY = e.clientY
      const dialog = this.$refs.dialog
      this.startLeft = dialog.offsetLeft
      this.startTop = dialog.offsetTop

      document.addEventListener('mousemove', this.handleDrag)
      document.addEventListener('mouseup', this.stopDrag)
    },
    handleDrag(e) {
      if (!this.isDragging) return
      const dialog = this.$refs.dialog
      const dx = e.clientX - this.startX
      const dy = e.clientY - this.startY
      dialog.style.left = `${this.startLeft + dx}px`
      dialog.style.top = `${this.startTop + dy}px`
    },
    stopDrag() {
      this.isDragging = false
      document.removeEventListener('mousemove', this.handleDrag)
      document.removeEventListener('mouseup', this.stopDrag)
    }
  }
}
</script>

<style>
.dialog-wrapper {
  position: fixed;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 300px;
  border: 1px solid #ccc;
  background: white;
  z-index: 1000;
}

.dialog-header {
  padding: 10px;
  background: #f0f0f0;
  cursor: move;
  display: flex;
  justify-content: space-between;
}

.dialog-content {
  padding: 15px;
}
</style>

注意事项

确保拖拽元素设置了正确的 CSS 定位属性(如 position: absolute 或 position: fixed)

对于复杂的拖拽场景,考虑使用第三方库如 interact.js 或 sortablejs

移动端支持需要额外处理 touch 事件

vue实现弹窗拖拽排序

拖拽性能优化:对于大量元素,使用虚拟滚动等技术

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

相关文章

vue实现按卡片轮播

vue实现按卡片轮播

实现卡片轮播的基本思路 在Vue中实现卡片轮播可以通过结合v-for指令和动态样式绑定完成。核心是维护一个当前显示卡片的索引,通过CSS过渡效果实现平滑切换。 基础实现步骤 模板部分 使用v-for…

vue实现文字

vue实现文字

Vue 中实现文字显示的方法 在 Vue 中实现文字显示可以通过多种方式,包括插值表达式、指令、组件等。以下是几种常见的实现方法: 插值表达式 使用双大括号 {{ }} 进行文本插值,这是 Vue…

vue实现粘贴

vue实现粘贴

Vue 实现粘贴功能的方法 在 Vue 中实现粘贴功能通常涉及监听粘贴事件并处理剪贴板数据。以下是几种常见的实现方式: 监听原生粘贴事件 通过 @paste 指令或原生 addEventListen…

vue实现ajax

vue实现ajax

Vue 中实现 AJAX 的几种方法 在 Vue 中实现 AJAX 请求可以通过原生 JavaScript 的 XMLHttpRequest、第三方库如 axios 或 fetch API 来完成。以…

vue实现视频

vue实现视频

Vue 实现视频播放的方法 在 Vue 项目中实现视频播放可以通过多种方式完成,以下是几种常见的方法: 使用 HTML5 的 <video> 标签 在 Vue 组件中直接使用 HTML…

vue toast实现

vue toast实现

Vue Toast 实现方法 使用第三方库(推荐) 安装 vue-toastification 库,这是一个功能丰富且轻量级的 Vue Toast 插件。 npm install vue-toast…