Vue 3 自定义指令实战:实现一个轻量级拖拽神器

在前端开发中,我们经常遇到这样的需求:用户需要拖动一个弹窗、卡片、对话框等元素。虽然市面上有很多现成的库,但你有没有想过,其实我们只需要十几行代码,就能用 Vue 3 的 自定义指令 实现这一效果?

本文将带你从零开始,一步步实现一个支持 v-drag 拖拽指令,轻松控制 DOM 元素移动,彻底掌握 Vue 3 自定义指令的高级用法。

最终效果
你可以为任意元素加上 `v-drag` 指令,即可实现拖动效果。还能通过 `.v-drag-handle` 类名指定“只拖动标题栏”的行为。

<div class=”my-dialog” v-drag zindexEnable fixed>
<div class=”v-drag-handle”>拖动我试试~</div>
<p>内容内容内容…</p>
</div>

为什么用指令而不是组件?
虽然组件封装更彻底,但拖拽是一种“DOM 行为增强”,使用自定义指令更轻量、解耦性更高,几乎可以应用到任意元素,无需额外结构。这也是指令非常适合做拖拽的原因。

第一步:创建自定义指令 v-drag
我们先新建一个 v-drag.js 文件,实现一个 Vue 插件,提供 v-drag 指令。

// v-drag.js
let baseZindex = 999;
let index = 0;
let max = 0;

const createDirective = (name = ‘drag’) => ({
install(app) {
app.directive(name, {
mounted(el) {
const isFixed = el.hasAttribute(“fixed”);
const handle = el.querySelector(‘.v-drag-handle’) || el;
const zindexEnable = el.hasAttribute(“zindexEnable”);

let disX = 0;
let disY = 0;
let curClientX = 0;
let curClientY = 0;

if (zindexEnable) {
el.dataset.zindex = index;
el.style.zIndex = baseZindex + index;
}
index++;
max = index;

const onMouseDown = (e) => {
curClientX = e.clientX;
curClientY = e.clientY;

const rect = el.getBoundingClientRect();
disX = e.clientX – (isFixed ? rect.left : el.offsetLeft);
disY = e.clientY – (isFixed ? rect.top : el.offsetTop);

if (zindexEnable && Number(el.dataset.zindex) < max) {
el.dataset.zindex = ++max – 1;
el.style.zIndex = baseZindex + max – 1;
}

document.addEventListener(‘mousemove’, onMouseMove);
document.addEventListener(‘mouseup’, onMouseUp);
};

const onMouseMove = (e) => {
const left = e.clientX – disX;
const top = e.clientY – disY;

el.style.position = isFixed ? ‘fixed’ : ‘absolute’;
Object.assign(el.style, {
left: `${left}px`,
top: `${top}px`,
right: ‘auto’,
bottom: ‘auto’,
});
};

const onMouseUp = () => {
document.removeEventListener(‘mousemove’, onMouseMove);
document.removeEventListener(‘mouseup’, onMouseUp);
};

handle.addEventListener(‘mousedown’, onMouseDown);

el._dragCleanup = () => {
handle.removeEventListener(‘mousedown’, onMouseDown);
};
},
unmounted(el) {
el._dragCleanup?.();
delete el._dragCleanup;
}
});
}
});

export default createDirective();

第二步:注册全局指令
在 main.js 中全局注册该插件:

// main.js
import { createApp } from ‘vue’;
import App from ‘./App.vue’;
import vDrag from ‘./v-drag.js’;

const app = createApp(App);
app.use(vDrag); // 默认指令名是 v-drag
app.mount(‘#app’);

第三步:使用拖拽指令
你现在可以在任何组件中使用 v-drag,也可以通过加 zindexEnable 和 fixed 控制叠层与定位模式。

<template>
<div class=”dialog” v-drag fixed zindexEnable>
<div class=”v-drag-handle”>标题拖动区</div>
<p>这是一个可拖拽弹窗!</p>
</div>
</template>

实用技巧小结Vue 3 自定义指令实战:实现一个轻量级拖拽神器

关于我
最近在学习油猴脚本开发,写了很多有趣的脚本:

接口拦截工具:修改CSDN博客数据接口返回值

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

Vue路由一键切换:开发效率起飞

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

任意元素双击实现画中画:摸鱼超级助手

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

掘金后台自动签到助手

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

解除文本复制、网页复制、一键下载为MD

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

主题切换助手

Vue 3 自定义指令实战:实现一个轻量级拖拽神器

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请不要用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"dtmb.taobao.com",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性

山喂资源分享 其它教程 Vue 3 自定义指令实战:实现一个轻量级拖拽神器 https://www.023140.com/622.html

Vue 3 自定义指令实战:实现一个轻量级拖拽神器
下一篇:

已经没有下一篇了!

常见问题
  • 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。 若排除这种情况,可在对应资源底部留言,或 联络我们.。
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务