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

实现思路

  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.mzph.cn/pingmian/67684.shtml

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

相关文章

Ubuntu、Windows系统网络设置(ping通内外网)

一、 虚拟机VMware和Ubuntu系统的网络配置说明 1、虚拟机的网络适配器的模式有三种&#xff1a; 桥接模式NAT模式主机模式 2、虚拟机VMware的网卡配置(如何进行配置界面(虚拟机->设置)) 注意&#xff1a; 1、以上桥接模式(ubuntu有独立IP)、NAT模式(没有独立IP)都可以联…

将IDLE里面python环境pyqt5配置的vscode

首先安装pyqt5全套&#xff1a;pip install pyqt5-tools 打开Vscode&#xff1a; 安装第三方扩展&#xff1a;PYQT Integration 成功配置designer.exe的路径【个人安装pyqt5的执行路径】&#xff0c;便可直接打开UI文件&#xff0c;进行编辑。 配置pyuic,如果下图填写方法使用…

C# OpenCV机器视觉:特征匹配 “灵魂伴侣”

在一个阳光仿佛被施了魔法&#xff0c;欢快得直蹦跶的早晨&#xff0c;阿强像个即将踏上神秘寻宝之旅的探险家&#xff0c;一屁股墩在实验室那张堆满各种奇奇怪怪小玩意儿的桌前。桌上&#xff0c;零件、线路、半成品设备乱成一团&#xff0c;唯有他那宝贝电脑屏幕散发着清冷又…

简述mysql 主从复制原理及其工作过程,配置一主两从并验证

第一种基于binlog的主从同步 首先对主库进行配置&#xff1a; [rootopenEuler-1 ~]# vim /etc/my.cnf 启动服务 [rootopenEuler-1 ~]# systemctl enable --now mysqld 主库的配置 从库的配置 第一个从库 [rootopenEuler-1 ~]# vim /etc/my.cnf [rootopenEuler-1 ~]# sys…

Spring自定义BeanPostProcessor实现bean的代理Java动态代理知识

上文&#xff1a;https://blog.csdn.net/qq_26437925/article/details/145241149 中大致了解了spring aop的代理的实现&#xff0c;其实就是有个BeanPostProcessor代理了bean对象。顺便复习下java代理相关知识 目录 自定义BeanPostProcessor实现aopJava动态代理知识动态代理的几…

医院挂号就诊系统设计与实现(代码+数据库+LW)

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装医院挂号就诊系统软件来发挥其高效地信息处理的作用&#…

【GORM】初探gorm模型,字段标签与go案例

GORM是什么&#xff1f; GORM 是一个Go 语言 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它让我们可以使用结构体来操作数据库&#xff0c;而无需编写SQL 语句 GORM 模型与字段标签详解 在 GORM 中&#xff0c;模型是数据库表的抽象表示&#xff0c;字段标签&am…

R 语言科研绘图第 20 期 --- 箱线图-配对

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…

【物联网】ARM核介绍

文章目录 一、芯片产业链1. CPU核(1)ARM(2)MIPS(3)PowerPc(4)Intel(5)RISC-V 2. SOC芯片(1)主流厂家(2)产品解决方案 3. 产品 二、ARM核发展1. 不同架构的特点分析(1)VFP(2)Jazelle(3)Thumb(4)TrustZone(5)SIMD(6)NEON 三、ARM核(ARMv7)工作模式1. 权限级别(privilege level)2.…

uniApp开通uniPush1.0个推,SpringBoot集成uniPush1.0个推

uniApp开通unipush1.0个推&#xff0c;SpringBoot程序集成 一、APP开通unipush1.0个推(商户App源码仅支持1.0个推) 1.app模块配置开通推送 2.应用开通推送 3.开通后点击消息推送菜单会看到如下页面 完成以上步骤后 此时android 仅支持在线推送。 4.配置各厂商离线推送 暂未…

JS宏进阶: 工厂函数与构造函数

一、构造函数 在JavaScript中&#xff0c;构造函数是一种用于创建和初始化对象的特殊函数。构造函数的名字通常以大写字母开头&#xff0c;以区分于普通函数。通过new关键字调用构造函数&#xff0c;可以创建一个新的实例对象&#xff0c;并自动执行构造函数内部的代码来初始化…

03_UI自适应

因为Canvas大小是始终和屏幕一致的 所以设置Canvas的屏幕大小 通常设置为1920 * 1080 又因为屏幕的图像及按钮如果想适配各种显示屏需要锁定长或者宽&#xff0c; 之后利用钉子将其他图像利用创建空节点定在左右或者上下两侧 比如unity编辑器通常是锁定宽的&#xff0c;那我…

网络安全——常用语及linux系统

一、网络安全概念及法规 网络安全&#xff1a;网络空间安全 cyber security 信息系统&#xff1a;由计算机硬件、网络和通信设备、计算机软件、信息资源、信息用户和规章制度组成的已处理信息流为目的的人机一体化系统 信息系统安全三要素&#xff08;CIA&#xff09; 保密…

算法日记6.StarryCoding P52:我们都需要0(异或)

一、题目 二、题解&#xff1a; 1、对于这道题&#xff0c;题意为让我们寻找一个数x使得 b[i]a[i]^x&#xff0c; 并且b[1]^b[2]^b[3]^ b[4]^b[5]....0 2、我们把b[i]给拆开&#xff0c;可以得到 3、又因为^满足结合律&#xff0c;因此&#xff0c;可以把括号给拆开 4、接着…

提问:玩游戏输入法总弹出来咋回事哎

玩游戏时输入法总弹出来的问题&#xff0c;通常与电脑的输入法设置、操作系统配置以及游戏程序的兼容性有关。以下是一些常见的解决方法&#xff1a; 一、修改输入法快捷键 禁用不必要的输入法&#xff1a; 在系统的语言设置中&#xff0c;暂时禁用非活动的输入法&#xff0c;…

通过内核模块按fd强制tcp的quickack方法

一、背景 tcp的quickack功能是为了让ack迅速回发&#xff0c;快速响应&#xff0c;减少网络通讯时延&#xff0c;属于一个优化项&#xff0c;但是tcp的quickack是有配额限制的&#xff0c;配置是16个quick&#xff0c;也就是短时间内quickack了16次以后&#xff0c;这个配额为…

csp22前2题

一幅长宽分别为 nn 个像素和 mm 个像素的灰度图像可以表示为一个 nmnm 大小的矩阵 AA。 其中每个元素 AijAij&#xff08;0≤i<n0≤i<n、0≤j<m0≤j<m&#xff09;是一个 [0,L)[0,L) 范围内的整数&#xff0c;表示对应位置像素的灰度值。 具体来说&#xff0c;一…

《汽车与驾驶维修》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答&#xff1a; 问&#xff1a;《汽车与驾驶维修》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第二批认定学术期刊。 问&#xff1a;《汽车与驾驶维修》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;中国机械工业联合会…

web前端1--基础

&#xff08;时隔数月我又来写笔记啦~&#xff09; 1、下载vscode 1、官网下载&#xff1a;Visual Studio Code - Code Editing. Redefined 2、步骤&#xff1a; 1、点击同意 一直下一步 勾一个创建桌面快捷方式 在一直下一步 2、在桌面新建文件夹 拖到vscode图标上 打开v…

vue 学习笔记 - 创建第一个项目 idea

1、安装Vue CLI 查看npm版本号 &#xff08;可跳过&#xff09; % npm -v 11.0.0安装Vue CLI % npm install -g vue/cli2、创建项目 进入工程文件目录 % cd /Users/ruizhifeng/work/aina-client查看vue 版本号 &#xff08;可跳过&#xff09; % vue --version vue/cli 5…