当前位置:首页 > 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 实现边框的方法 在 Vue 中实现边框效果可以通过多种方式完成,包括内联样式、CSS 类绑定、动态样式以及使用第三方 UI 库。以下是几种常见的实现方法。 内联样式绑定 使用 Vue 的 :…

vue插件实现

vue插件实现

Vue 插件实现方法 Vue 插件是一种向 Vue 应用程序添加全局功能的机制。插件可以包含全局指令、过滤器、混入、实例方法等。 插件的基本结构 一个 Vue 插件通常是一个对象或函数,需要暴露一个…

vue实现ide

vue实现ide

Vue 实现 IDE 的基本思路 使用 Vue 构建一个简易的集成开发环境(IDE)需要整合代码编辑器、文件管理、终端模拟等功能。以下是关键实现步骤和推荐工具。 核心功能模块 代码编辑器 使用…

vue实现阻塞

vue实现阻塞

Vue 实现阻塞的方法 在 Vue 中实现阻塞操作通常涉及异步控制、状态管理或生命周期钩子的使用。以下是几种常见方法: 使用 async/await 处理异步阻塞 通过 async/await 可…

vue nexttrick实现

vue nexttrick实现

Vue 中 nextTick 的实现原理 nextTick 是 Vue 提供的一个异步方法,用于在下次 DOM 更新循环结束之后执行延迟回调。它利用了 JavaScript 的事件循环机制,确保回调在…

vue实现checkbox

vue实现checkbox

Vue 实现 Checkbox 在 Vue 中实现 Checkbox 可以通过原生 HTML 的 <input type="checkbox"> 或使用 Vue 的 v-model 指令绑…