vue 通过 directives 实现弹窗div可以拖动

在 Vue 2 中,可以通过自定义指令(v-draggable)来实现弹窗 div 拖动的功能。自定义指令允许我们将拖动功能封装起来,使得在多个地方复用。下面是一个实现拖动功能的完整示例:

实现步骤:

  1. 创建一个自定义指令 v-draggable 来处理拖动逻辑。
  2. 将该指令应用于你想要拖动的元素(例如弹窗 div)。

示例代码:

<template>
  <div class="app">
    <div
      v-draggable
      class="draggable-window"
      :style="{ left: position.x + 'px', top: position.y + 'px' }"
    >
      <div class="window-header">
        <span>拖动弹窗</span>
      </div>
      <div class="window-content">
        <p>这里是弹窗内容</p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      position: { x: 100, y: 100 }, // 初始位置
    };
  },
};
</script>

<script>
// 自定义指令 v-draggable
Vue.directive('draggable', {
  bind(el) {
    let isDragging = false;   // 是否正在拖动
    let offsetX = 0;          // 鼠标与元素的水平偏移
    let offsetY = 0;          // 鼠标与元素的垂直偏移

    // 鼠标按下事件
    const onMouseDown = (event) => {
      isDragging = true;
      offsetX = event.clientX - el.offsetLeft;
      offsetY = event.clientY - el.offsetTop;
      
      // 阻止选中文本
      document.body.style.userSelect = 'none';

      // 绑定鼠标移动和鼠标释放事件
      document.addEventListener('mousemove', onMouseMove);
      document.addEventListener('mouseup', onMouseUp);
    };

    // 鼠标移动事件
    const onMouseMove = (event) => {
      if (isDragging) {
        // 更新元素的位置
        el.style.left = `${event.clientX - offsetX}px`;
        el.style.top = `${event.clientY - offsetY}px`;
      }
    };

    // 鼠标释放事件
    const onMouseUp = () => {
      isDragging = false;
      
      // 恢复文本选择
      document.body.style.userSelect = '';

      // 移除事件监听
      document.removeEventListener('mousemove', onMouseMove);
      document.removeEventListener('mouseup', onMouseUp);
    };

    // 绑定鼠标按下事件到目标元素
    el.querySelector('.window-header').addEventListener('mousedown', onMouseDown);
  }
});
</script>

<style scoped>
.app {
  position: relative;
}

.draggable-window {
  position: absolute;
  width: 300px;
  height: 200px;
  border: 1px solid #ccc;
  background-color: white;
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
  cursor: move;
}

.window-header {
  background-color: #f1f1f1;
  padding: 10px;
  cursor: move;
  font-weight: bold;
}

.window-content {
  padding: 20px;
}
</style>

解释

1. 自定义指令 v-draggable

  • bind 钩子:这个钩子在指令绑定到元素时被调用。我们在这个钩子里添加了拖动的逻辑。

  • onMouseDown:当用户按下鼠标时,记录鼠标和元素的偏移量,并开始监听 mousemovemouseup 事件。

  • onMouseMove:在鼠标移动时,如果处于拖动状态,更新元素的位置。

  • onMouseUp:当用户释放鼠标时,停止拖动并移除事件监听。

2. 样式:

  • .draggable-window 使用 position: absolute,使得元素可以随意定位,并且添加了 cursor: move 来指示该元素是可拖动的。

  • .window-header 设置了拖动区域,用户可以点击这个区域来拖动整个窗口。

3. 如何使用:

在 HTML 代码中,将 v-draggable 指令应用于需要拖动的元素。该指令会自动为指定的元素添加拖动行为。

4. 注意事项:

  • v-draggable 指令默认只能在 .window-header 部分触发拖动。你可以根据需要修改为任何元素来控制拖动区域。

  • 如果你希望限制窗口的拖动范围,可以在 onMouseMove 中添加限制逻辑,确保窗口不会超出某个区域。

优化和扩展:

  • 限制窗口范围:通过限制 el.style.leftel.style.top 的最大值和最小值,来防止弹窗被拖出视窗。

  • 响应式设计:如果希望窗口在不同屏幕尺寸下也能够适应,可以动态设置 lefttop

总结:

使用自定义指令 v-draggable 可以简洁地为 Vue 2 中的弹窗或任何元素实现拖动功能。这样,我们的拖动逻辑可以在不同的组件中复用,并且避免了冗余的代码。

======

这种方式实际是可行的,项目中看到这种用法,但上面的答案来自chatgpt,没验证过

posted @   盘思动  阅读(184)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
历史上的今天:
2022-12-27 地图飞线图
点击右上角即可分享
微信分享提示