当前位置:首页 > VUE

vue实现弹框拖动

2026-02-24 16:43:31VUE

Vue 实现弹框拖动功能

核心思路

通过监听鼠标事件(mousedown、mousemove、mouseup)计算弹框的偏移量,结合 CSS 的 transformposition 属性实现拖动效果。

基础实现代码

<template>
  <div 
    class="draggable-dialog" 
    ref="dialog"
    :style="{ left: position.x + 'px', top: position.y + 'px' }"
    @mousedown="startDrag"
  >
    <!-- 弹框内容 -->
    <div class="dialog-content">
      <slot></slot>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      position: { x: 0, y: 0 },
      isDragging: false,
      startPos: { x: 0, y: 0 }
    };
  },
  methods: {
    startDrag(e) {
      this.isDragging = true;
      this.startPos = {
        x: e.clientX - this.position.x,
        y: e.clientY - this.position.y
      };
      document.addEventListener('mousemove', this.onDrag);
      document.addEventListener('mouseup', this.stopDrag);
    },
    onDrag(e) {
      if (!this.isDragging) return;
      this.position = {
        x: e.clientX - this.startPos.x,
        y: e.clientY - this.startPos.y
      };
    },
    stopDrag() {
      this.isDragging = false;
      document.removeEventListener('mousemove', this.onDrag);
      document.removeEventListener('mouseup', this.stopDrag);
    }
  }
};
</script>

<style>
.draggable-dialog {
  position: absolute;
  cursor: move;
  user-select: none;
}
</style>

优化方案

限制拖动范围onDrag 方法中添加边界检测:

vue实现弹框拖动

onDrag(e) {
  if (!this.isDragging) return;
  const maxX = window.innerWidth - this.$refs.dialog.offsetWidth;
  const maxY = window.innerHeight - this.$refs.dialog.offsetHeight;

  this.position = {
    x: Math.min(maxX, Math.max(0, e.clientX - this.startPos.x)),
    y: Math.min(maxY, Math.max(0, e.clientY - this.startPos.y))
  };
}

使用 transform 优化性能 修改样式和计算方式:

vue实现弹框拖动

.draggable-dialog {
  position: fixed;
  transform: translate(0, 0);
}
position: {
  x: 0,
  y: 0
},
// 在 onDrag 中:
this.position = {
  x: e.clientX - this.startPos.x,
  y: e.clientY - this.startPos.y
};

组件化方案

创建可复用的 Draggable 高阶组件:

// Draggable.js
export default {
  props: ['x', 'y'],
  data() {
    return {
      position: { x: this.x || 0, y: this.y || 0 },
      // ...其他拖动逻辑
    };
  },
  // ...其他方法
};

使用时:

<Draggable :x="100" :y="100">
  <YourDialogComponent />
</Draggable>

注意事项

  1. 移动端需要额外处理 touchstart/touchmove 事件
  2. 复杂场景建议使用第三方库如:
    • vuedraggable
    • interact.js
  3. 拖动时禁用文本选择:
    .draggable-dialog {
      user-select: none;
    }

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

相关文章

vue实现轮询

vue实现轮询

实现轮询的基本方法 在Vue中实现轮询可以通过setInterval或setTimeout配合递归调用完成。轮询通常用于定期向服务器请求数据更新。 使用setInterval的简单示例: data…

vue 实现排序

vue 实现排序

Vue 实现排序的方法 使用计算属性实现排序 通过计算属性对数组进行排序,可以保持原始数据不变。示例代码展示了如何对列表按名称升序排序: <template> <div>…

vue 实现遮罩

vue 实现遮罩

Vue 实现遮罩层的方法 使用固定定位和透明背景 在Vue中实现遮罩层可以通过CSS固定定位结合透明背景色完成。创建一个全屏遮罩组件,利用position: fixed覆盖整个视窗。 <tem…

vue实现eventbus

vue实现eventbus

Vue 中实现 EventBus 在 Vue 中,EventBus 是一种跨组件通信的机制,尤其适用于非父子组件之间的数据传递。以下是实现 EventBus 的几种方法: 方法一:使用 Vue 实例…

vue实现vr

vue实现vr

Vue 实现 VR 的方法 Vue 可以与 WebVR 或 WebXR API 结合使用,通过 Three.js、A-Frame 等库实现 VR 效果。以下是几种常见方法: 使用 A-Frame 框…

vue实现gridlayout

vue实现gridlayout

Vue 实现 Grid Layout 使用 CSS Grid 布局 CSS Grid 是一种强大的布局系统,可以直接在 Vue 组件的样式中使用。通过定义网格容器和网格项,可以快速实现复杂的布局结构。…