vue编写一个可拖动的模块,并可以和任何其他组件组合使用

news2025/1/18 13:48:18

实现思路

  1. 使用 Vue 的自定义指令(directive)来处理拖动逻辑。
  2. mounted 钩子中添加鼠标事件监听器,以实现拖动功能。
  3. unmounted 钩子中移除鼠标事件监听器,防止内存泄漏。

代码示例

<template>
  <div v-draggable class="draggable-component">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'DraggableComponent',
  directives: {
    draggable: {
      // 当绑定元素插入到 DOM 中时
      mounted(el) {
        let isDragging = false;
        let initialX, initialY;
        let offsetX = 0, offsetY = 0;

        const handleMouseDown = (e) => {
          isDragging = true;
          initialX = e.clientX - offsetX;
          initialY = e.clientY - offsetY;
        };

        const handleMouseMove = (e) => {
          if (isDragging) {
            offsetX = e.clientX - initialX;
            offsetY = e.clientY - initialY;
            el.style.transform = `translate3d(${offsetX}px, ${offsetY}px, 0)`;
          }
        };

        const handleMouseUp = () => {
          isDragging = false;
        };

        el.addEventListener('mousedown', handleMouseDown);
        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);

        // 在元素销毁时移除事件监听器
        el._removeEventListeners = () => {
          el.removeEventListener('mousedown', handleMouseDown);
          document.removeEventListener('mousemove', handleMouseMove);
          document.removeEventListener('mouseup', handleMouseUp);
        };
      },
      unmounted(el) {
        if (el._removeEventListeners) {
          el._removeEventListeners();
        }
      }
    }
  }
};
</script>

<style scoped>
.draggable-component {
  position: absolute;
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  padding: 10px;
  cursor: move;
}
</style>

代码解释

  • 模板部分

    • <div v-draggable class="draggable-component">:使用自定义指令 v-draggable 使该 div 元素具有可拖动的功能。
    • <slot></slot>:使用插槽,允许其他组件或内容插入到这个可拖动的 div 中,从而实现与其他组件的组合使用。
  • 脚本部分

    • directives:定义了一个名为 draggable 的自定义指令。
      • mounted 钩子:
        • isDragging:用于标记是否正在拖动。
        • initialXinitialY:记录鼠标按下时的初始位置。
        • offsetXoffsetY:存储元素相对于初始位置的偏移量。
        • handleMouseDown:当鼠标按下时触发,标记为正在拖动,并记录初始位置。
        • handleMouseMove:当鼠标移动且正在拖动时触发,计算偏移量并更新元素的 transform 属性,使用 translate3d 进行元素的平移。
        • handleMouseUp:当鼠标松开时触发,标记为停止拖动。
        • 添加鼠标事件监听器:为元素添加 mousedown 事件监听器,为文档添加 mousemovemouseup 事件监听器。
        • el._removeEventListeners:存储一个函数,用于移除事件监听器。
      • unmounted 钩子:在元素销毁时调用 el._removeEventListeners 移除事件监听器,防止内存泄漏。

使用示例

<template>
  <div id="app">
    <DraggableComponent>
      <h1>可拖动的组件</h1>
      <p>这是一个可以拖动的模块,并且可以和任何其他组件组合使用。</p>
      <AnotherComponent></AnotherComponent>
    </DraggableComponent>
  </div>
</template>

<script>
import DraggableComponent from './DraggableComponent.vue';
import AnotherComponent from './AnotherComponent.vue';

export default {
  name: 'App',
  components: {
    DraggableComponent,
    AnotherComponent
  }
};
</script>

解释

  • 首先,将 DraggableComponent 组件导入并注册。
  • 在模板中使用 DraggableComponent 组件,并在其内部使用插槽插入了一个 h1 元素、一个 p 元素和 AnotherComponent 组件,这样就实现了一个可拖动的组件,并且可以方便地与其他组件组合使用。

注意事项

  • 确保在 unmounted 钩子中移除事件监听器,以避免内存泄漏。
  • 该示例只是一个简单的实现,你可以根据需求扩展功能,例如限制拖动范围、添加拖动手柄等。

通过上述方法,你可以在 Vue 中实现一个可拖动的模块,并将其与任何其他组件进行组合使用。如果你需要更复杂的拖动功能,例如与其他组件进行交互或支持多个可拖动元素,可以考虑使用第三方库,如 vue-draggablevue-draggable-resizable。这些库提供了更丰富的功能和更强大的拖动、调整大小等操作。

还有其他方法实现可拖动模块吗?

另一种在 Vue 中实现可拖动模块的方法,使用 Vue 的 ref 和组件方法来处理拖动逻辑:

实现思路

  1. 使用 ref 获取元素引用。
  2. 在组件的 mounted 生命周期中添加鼠标事件监听器。
  3. 在鼠标按下、移动和松开时更新元素的位置。

代码示例

<template>
  <div ref="draggable" class="draggable-component">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'DraggableComponent',
  data() {
    return {
      isDragging: false,
      startX: 0,
      startY: 0,
      offsetX: 0,
      offsetY: 0
    };
  },
  mounted() {
    const draggable = this.$refs.draggable;
    const handleMouseDown = (e) => {
      this.isDragging = true;
      this.startX = e.clientX - this.offsetX;
      this.startY = e.clientY - this.offsetY;
    };
    const handleMouseMove = (e) => {
      if (this.isDragging) {
        this.offsetX = e.clientX - this.startX;
        this.offsetY = e.clientY - this.startY;
        draggable.style.transform = `translate3d(${this.offsetX}px, ${this.offsetY}px, 0)`;
      }
    };
    const handleMouseUp = () => {
      this.isDragging = false;
    };
    draggable.addEventListener('mousedown', handleMouseDown);
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    // 在组件销毁时移除事件监听器
    this.$once('hook:beforeDestroy', () => {
      draggable.removeEventListener('mousedown', handleMouseDown);
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    });
  }
};
</script>

<style scoped>
.draggable-component {
  position: absolute;
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  padding: 10px;
  cursor: move;
}
</style>

代码解释

  • 模板部分

    • <div ref="draggable" class="draggable-component">:使用 ref 属性给 div 元素一个引用,方便在组件内部访问。
    • <slot></slot>:使用插槽,允许插入其他组件或内容。
  • 脚本部分

    • data 中存储拖动所需的状态:
      • isDragging:标记是否正在拖动。
      • startXstartY:鼠标按下时的初始位置。
      • offsetXoffsetY:元素相对于初始位置的偏移量。
    • mounted 生命周期钩子:
      • 通过 this.$refs.draggable 获取元素引用。
      • handleMouseDown:鼠标按下时记录初始位置并标记为正在拖动。
      • handleMouseMove:鼠标移动时计算偏移量并更新元素的 transform 属性,使用 translate3d 实现平移。
      • handleMouseUp:鼠标松开时标记为停止拖动。
      • 添加事件监听器:为可拖动元素添加 mousedown 事件监听器,为文档添加 mousemovemouseup 事件监听器。
      • this.$once('hook:beforeDestroy',...):在组件销毁前移除事件监听器,防止内存泄漏。

使用示例

<template>
  <div id="app">
    <DraggableComponent>
      <h1>可拖动的组件</h1>
      <p>这是另一种实现可拖动模块的方式,可以与其他组件组合使用。</p>
      <AnotherComponent></AnotherComponent>
    </DraggableComponent>
  </div>
</template>

<script>
import DraggableComponent from './DraggableComponent.vue';
import AnotherComponent from './AnotherComponent.vue';

export default {
  name: 'App',
  components: {
    DraggableComponent,
    AnotherComponent
  }
};
</script>

第三种方法:使用 Vue 3 的 Composition API 和 onMountedonUnmounted
如果你使用 Vue 3,还可以使用 Composition API 来实现:

<template>
  <div ref="draggable" class="draggable-component">
    <slot></slot>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted } from 'vue';

export default {
  name: 'DraggableComponent',
  setup() {
    const draggable = ref(null);
    let isDragging = ref(false);
    let startX = ref(0);
    let startY = ref(0);
    let offsetX = ref(0);
    let offsetY = ref(0);

    const handleMouseDown = (e) => {
      isDragging.value = true;
      startX.value = e.clientX - offsetX.value;
      startY.value = e.clientY - offsetY.value;
    };

    const handleMouseMove = (e) => {
      if (isDragging.value) {
        offsetX.value = e.clientX - startX.value;
        offsetY.value = e.clientY - startY.value;
        draggable.value.style.transform = `translate3d(${offsetX.value}px, ${offsetY.value}px, 0)`;
      }
    };

    const handleMouseUp = () => {
      isDragging.value = false;
    };

    onMounted(() => {
      if (draggable.value) {
        draggable.value.addEventListener('mousedown', handleMouseDown);
        document.addEventListener('mousemove', handleMouseMove);
        document.addEventListener('mouseup', handleMouseUp);
      }
    });

    onUnmounted(() => {
      if (draggable.value) {
        draggable.value.removeEventListener('mousedown', handleMouseDown);
        document.removeEventListener('mousemove', handleMouseMove);
        document.removeEventListener('mouseup', handleMouseUp);
      }
    });

    return {
      draggable
    };
  }
};
</script>

<style scoped>
.draggable-component {
  position: absolute;
  background-color: #f0f0f0;
  border: 1px solid #ccc;
  padding: 10px;
  cursor: move;
}
</style>

代码解释

  • 模板部分
    • 与之前类似,使用 ref 获取元素引用。
  • 脚本部分
    • 使用 ref 来创建响应式变量:draggable 用于存储元素引用,isDraggingstartXstartYoffsetXoffsetY 存储拖动状态。
    • handleMouseDownhandleMouseMovehandleMouseUp 函数处理鼠标事件。
    • onMounted 钩子添加事件监听器。
    • onUnmounted 钩子移除事件监听器。

这些方法都可以实现可拖动模块,你可以根据自己的喜好和项目使用的 Vue 版本选择合适的实现方式。如果你需要更复杂的拖动功能,例如拖动排序、拖动边界限制、与其他组件交互等,可能需要进一步扩展上述代码或使用第三方库,如 vue-draggablevue-draggable-resizable

你可以将上述代码复制到相应的 Vue 文件中进行测试和使用,根据自己的需求进行修改和扩展。如果还有其他需求,例如限制拖动范围或添加更多的交互功能,可以进一步细化上述代码或向我提出更具体的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2278493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IP属地会随着人的移动而改变吗

在当今数字化时代&#xff0c;互联网已成为人们生活中不可或缺的一部分。无论是社交媒体的日常互动&#xff0c;还是在线购物、远程工作&#xff0c;IP地址作为网络身份的重要标识&#xff0c;扮演着举足轻重的角色。随着移动互联网技术的飞速发展&#xff0c;人们越来越多地在…

我的世界-与门、或门、非门等基本门电路实现

一、红石比较器 (1) 红石比较器结构 红石比较器有前端单火把、后端双火把以及两个侧端 其中后端和侧端是输入信号,前端是输出信号 (2) 红石比较器的两种模式 比较模式 前端火把未点亮时处于比较模式 侧端>后端 → 0 当任一侧端强度大于后端强度时,输出…

【大数据】机器学习------支持向量机(SVM)

支持向量机的基本概念和数学公式&#xff1a; 1. 线性可分的支持向量机 对于线性可分的数据集 &#xff0c;其中(x_i \in R^d) 是特征向量 是类别标签&#xff0c;目标是找到一个超平面 &#xff0c;使得对于所有 的样本 &#xff0c;对于所有(y_i -1) 的样本&#xff0c;…

RDD和DataFrame两种数据结构的对比

文章目录 1. 实战概述2. RDD&#xff08;弹性分布式数据集&#xff09;2.1 RDD概念2.2 RDD特点2.3 实战操作 3. DataFrame&#xff08;数据帧&#xff09;3.1 DataFrame概念3.2 DataFrame优点3.3 实战操作 4. 实战小结 1. 实战概述 今天我们将深入探讨 Apache Spark 中的两种核…

中职网络建设与运维ansible服务

ansible服务 填写hosts指定主机范围和控制节点后创建一个脚本&#xff0c;可以利用简化脚本 1. 在linux1上安装系统自带的ansible-core,作为ansible控制节点,linux2-linux7作为ansible的受控节点 Linux1 Linux1-7 Yum install ansible-core -y Vi /etc/ansible/hosts 添加…

Kibana 控制台中提供语义、向量和混合搜索

作者&#xff1a;来自 Elastic Mark_Laney 想要将常规 Elasticsearch 查询与新的 AI 搜索功能结合起来吗&#xff1f;那么&#xff0c;你不需要连接到某个第三方的大型语言模型&#xff08;LLM&#xff09;吗&#xff1f;不。你可以使用 Elastic 的 ELSER 模型来改进现有搜索&a…

多种 Docker 镜像拉取解决方案与实践

最近国内 Docker 镜像拉取不太通畅&#xff0c;尝试了几种镜像拉取的方式&#xff0c;写篇博客分享一下。 原以为只是 docker hub 被毙了&#xff0c;上机器一操作&#xff0c;官方的下载地址也被毙了&#xff0c;真是从源头解决问题。 不过还好目前还有其他源能用&#xff0…

2025边缘计算新年沙龙成功举办,共话边缘AI未来

1月11日下午&#xff0c;北京市海淀区中关村创业大街热闹非凡&#xff0c;以“云边腾跃&#xff0c;蛇启新航”为主题的 2025边缘计算新年沙龙 盛大举行。本次活动汇聚了边缘计算、人工智能以及云边协同领域的顶尖专家、学者和从业者&#xff0c;共同探讨技术前沿与实际应用场景…

使用redis-cli命令实现redis crud操作

项目场景&#xff1a; 线上环境上redis中的key影响数据展示&#xff0c;需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤&#xff1a; 1、确定redis安装的服务器&#xff1b; 2、找到redis的安装目录下 ##找到redis安装目…

CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法

下载软件时出现以下问题 直接把CentOS-AppStream.repo改个名字就行 cd /etc/yum.repos.d/ mv CentOS-AppStream.repo CentOS-AppStream.repo.bak就可以了 解决思路 把AI问遍&#xff0c;无人会&#xff0c;解决法 想要下载软件通通失败了&#xff0c;解决方法当然是问AI&am…

【深度学习】神经网络之Softmax

Softmax 函数是神经网络中常用的一种激活函数&#xff0c;尤其在分类问题中广泛应用。它将一个实数向量转换为概率分布&#xff0c;使得每个输出值都位于 [0, 1] 之间&#xff0c;并且所有输出值的和为 1。这样&#xff0c;Softmax 可以用来表示各类别的预测概率。 Softmax 函…

python管理工具:conda部署+使用

python管理工具&#xff1a;conda部署使用 一、安装部署 1、 下载 - 官网下载&#xff1a; https://repo.anaconda.com/archive/index.html - wget方式&#xff1a; wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh2、 安装 在conda文件的…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…

unity——Preject3——开始界面拼面板

目录 1.创建panel&#xff0c;去掉panel自带的image&#xff0c;自己加一个image&#xff0c;使用锚点分配好 2.锚点&#xff08;快捷键点击后 ALTShift&#xff09; 锚点是什么&#xff1f; 锚点的实际例子 例子1&#xff1a;固定在父容器的中心 例子2&#xff1a;对齐到…

PyTorch使用教程(6)一文讲清楚torch.nn和torch.nn.functional的区别

torch.nn 和 torch.nn.functional 在 PyTorch 中都是用于构建神经网络的重要组件&#xff0c;但它们在设计理念、使用方式和功能上存在一些显著的区别。以下是关于这两个模块的详细区别&#xff1a; 1. 继承方式与结构 torch.nn torch.nn 中的模块大多数是通过继承 torch.nn…

传统以太网问题与VLAN技术详解

传统以太网的问题 广播域&#xff1a;在网络中能接收同一广播信息的所有设备&#xff08;计算机、交换机&#xff09;等的集合 说明&#xff1a;在一个广播域内&#xff0c;当一个设备发送广播帧时&#xff0c;该域内的所有设备都能接收到这个广播帧。工作原理&#xff1a;在以…

OpenAI Whisper:语音识别技术的革新者—深入架构与参数

当下语音识别技术正以前所未有的速度发展&#xff0c;极大地推动了人机交互的便利性和效率。OpenAI的Whisper系统无疑是这一领域的佼佼者&#xff0c;它凭借其卓越的性能、广泛的适用性和创新的技术架构&#xff0c;正在重新定义语音转文本技术的规则。今天我们一起了解一下Whi…

WPS计算机二级•高效操作技巧

听说这里是目录哦 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9;横排转竖排&#x1f350;批量删除表格空白行&#x1f348;方法一方法二建辅助列找空值 能量站&#x1f61a; 斜线表头 展示项目名称&#x1f34b;‍&#x1f7e9; 选中单元格&#xff0c;单击右键➡️“设…

RabbitMQ实现延迟消息发送——实战篇

在项目中&#xff0c;我们经常需要使用消息队列来实现延迟任务&#xff0c;本篇文章就向各位介绍使用RabbitMQ如何实现延迟消息发送&#xff0c;由于是实战篇&#xff0c;所以不会讲太多理论的知识&#xff0c;还不太理解的可以先看看MQ的延迟消息的一个实现原理再来看这篇文章…

《Keras 3 在 TPU 上的肺炎分类》

Keras 3 在 TPU 上的肺炎分类 作者&#xff1a;Amy MiHyun Jang创建日期&#xff1a;2020/07/28最后修改时间&#xff1a;2024/02/12描述&#xff1a;TPU 上的医学图像分类。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub 源 简介 设置 本教程将介…