当前位置:首页 > VUE

vue 实现拖动

2026-02-10 04:41:30VUE

Vue 实现拖动功能

使用 HTML5 原生拖放 API

在 Vue 中可以通过 HTML5 的拖放 API 实现基本的拖动功能。需要监听 dragstartdragoverdrop 事件。

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

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

使用第三方库 vue-draggable

对于更复杂的拖动场景,推荐使用 vue-draggable 库。它基于 Sortable.js,提供了丰富的拖动功能。

安装:

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.directive('drag', {
  bind(el, binding) {
    let startX, startY, initialX, initialY

    el.style.position = 'absolute'

    el.addEventListener('mousedown', (e) => {
      startX = e.clientX
      startY = e.clientY
      initialX = el.offsetLeft
      initialY = el.offsetTop

      document.addEventListener('mousemove', move)
      document.addEventListener('mouseup', up)

      e.preventDefault()
    })

    function move(e) {
      const dx = e.clientX - startX
      const dy = e.clientY - startY

      el.style.left = initialX + dx + 'px'
      el.style.top = initialY + dy + 'px'
    }

    function up() {
      document.removeEventListener('mousemove', move)
      document.removeEventListener('mouseup', up)
    }
  }
})

拖动排序实现

结合 Vue 的响应式特性,可以实现拖动排序功能。

<template>
  <div 
    v-for="(item, index) in items" 
    :key="item.id"
    draggable="true"
    @dragstart="dragStart(index)"
    @dragover.prevent
    @dragenter="dragEnter(index)"
    @dragend="dragEnd"
  >
    {{ item.text }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, text: 'Item 1' },
        { id: 2, text: 'Item 2' }
      ],
      draggingIndex: null
    }
  },
  methods: {
    dragStart(index) {
      this.draggingIndex = index
    },
    dragEnter(index) {
      if (this.draggingIndex !== index) {
        const temp = this.items[this.draggingIndex]
        this.$set(this.items, this.draggingIndex, this.items[index])
        this.$set(this.items, index, temp)
        this.draggingIndex = index
      }
    },
    dragEnd() {
      this.draggingIndex = null
    }
  }
}
</script>

拖动边界限制

可以通过计算限制拖动元素的移动范围。

function move(e) {
  const dx = e.clientX - startX
  const dy = e.clientY - startY

  let newX = initialX + dx
  let newY = initialY + dy

  // 限制在父容器内
  const parentRect = el.parentElement.getBoundingClientRect()
  const elRect = el.getBoundingClientRect()

  newX = Math.max(0, Math.min(newX, parentRect.width - elRect.width))
  newY = Math.max(0, Math.min(newY, parentRect.height - elRect.height))

  el.style.left = newX + 'px'
  el.style.top = newY + 'px'
}

拖动性能优化

对于大量可拖动元素,应该使用事件委托来优化性能。

mounted() {
  this.$refs.container.addEventListener('mousedown', (e) => {
    if (e.target.classList.contains('draggable')) {
      // 拖动逻辑
    }
  })
}

触摸屏支持

为支持移动设备,需要添加触摸事件处理。

vue 实现拖动

el.addEventListener('touchstart', (e) => {
  startX = e.touches[0].clientX
  startY = e.touches[0].clientY
  // 其他逻辑类似鼠标事件
})

以上方法可以根据具体需求选择使用,从简单的原生 API 到功能完善的第三方库,Vue 提供了多种实现拖动功能的方案。

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

相关文章

vue实现switch

vue实现switch

Vue 实现 Switch 开关组件 在 Vue 中实现 Switch 开关组件可以通过自定义组件或使用现有 UI 库完成。以下是几种常见实现方式: 自定义 Switch 组件 创建一个基础 Sw…

vue环境实现

vue环境实现

Vue 环境搭建 安装 Node.js 和 npm Node.js 是运行 Vue 的基础环境,npm 是包管理工具。从 Node.js 官网 下载并安装最新稳定版本。安装完成后,在终端运行以下命令验…

vue实现加减

vue实现加减

Vue 实现加减功能 在 Vue 中实现加减功能可以通过数据绑定和事件监听来完成。以下是一个简单的实现方法: 模板部分 <template> <div> <…

vue实现城市

vue实现城市

Vue 实现城市选择功能 使用 Element UI 的 Cascader 组件 Element UI 提供了一个 Cascader 级联选择器组件,非常适合实现城市选择功能。需要先安装 Elemen…

vue实现hexo

vue实现hexo

Vue 集成 Hexo 的实现方法 Hexo 是一个静态博客框架,而 Vue 是一个前端框架。将 Vue 集成到 Hexo 中可以通过以下方式实现: 在 Hexo 中使用 Vue 组件 通过 Hex…

实现vue vm

实现vue vm

Vue VM 实现方法 Vue VM(ViewModel)是 Vue.js 的核心概念之一,负责连接视图(View)和数据模型(Model)。以下是实现 Vue VM 的几种方法: 使用 Vue 实…