目录
前言
在我的一个项目中有很多自定义的弹框,它们都需要可以随意拖拽,因此我封装了一个vue的自定义指令去实现,只要在需要拖动的元素上加上此指令即可变成可拖动元素。该组件除了可以让元素随意拖动,还能指定鼠标拖动元素上哪个区域才能拖动。
源码
在main.ts或main.js里注册:
const app = createApp(App);
app.directive('drag', (el, binding) => {
// 定义一个变量target来存储元素或者绑定的值
let target: any = null;
// 如果绑定了一个值,则将target设置为这个值,否则设置为el本身(即被拖拽的元素)
target = binding.value ? binding.value : el;
// 要实现拖动改变位置还需设置元素为绝对定位
target.style.position='absolute'
// 为元素添加鼠标按下事件监听,用于开始拖拽
el.onmousedown = (e) => {
// 阻止选择文本,防止在拖拽过程中选中文字
document.onselectstart = () => {
return false;
};
// 计算鼠标与目标元素之间的水平方向和垂直方向的距离
const disX = e.clientX - target.offsetLeft;
const disY = e.clientY - target.offsetTop;
// 为document添加鼠标移动事件监听
document.onmousemove = (e) => {
// 计算移动后的位置,并设置元素的新位置
const l = e.clientX - disX;
const t = e.clientY - disY;
if (l > 10 && t > 10) { // 判断移动的距离是否超过10像素,避免过于微小的移动
target.style.left = l + 'px';
target.style.top = t + 'px';
}
};
// 为document添加鼠标释放事件监听,用于结束拖拽
document.onmouseup = (e) => {
// 停止监听鼠标移动和释放事件,以及恢复onselectstart的行为
document.onmousemove = null;
document.onmouseup = null;
document.onselectstart = null;
};
// 阻止默认的鼠标按下事件行为
// return false不加的话可能导致黏连,即拖拽结束后鼠标依然被绑定在元素上
return false;
};
});
使用方式
1、拖动元素本身
在需要拖拽的元素上添加v-drag指令,即可实现对该元素的拖拽。在这种情况下,用户可以按住元素的任何区域进行拖拽。
<template>
<div class="drag_div" v-drag> </div>
</template>
<style>
.drag_div {
background-color: red;
height: 200px;
width: 200px;
}
</style>
按住红色方块任何区域都可以拖动,拖动的是整个红色方块
2、拖动指定区域
在元素上使用v-drag="xxx",其中xxx为需要拖拽元素的ref值。在这种情况下,用户只能按住添加了v-drag="xxx"的元素进行拖拽,实际被拖拽的是对应的ref元素。
<template>
<div class="drag_div" ref="dragRef">
<div class="inner_div" v-drag="dragRef"></div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const dragRef = ref();
</script>
<style>
.drag_div {
background-color: red;
height: 200px;
width: 200px;
}
.inner_div {
height: 50px;
width: 50px;
background-color: #f1b0b9;
}
</style>
只有按住红色方块里的粉色小方块时才能拖动,拖动的是整个红色方块 。
总结
该拖拽功能的实现原理主要是通过鼠标事件监听,计算鼠标与目标元素之间的距离,然后在鼠标移动时更新元素的位置。在鼠标释放时,清除相关的事件监听,结束拖拽操作。
这种拖拽功能的实现方式简洁明了,易于理解和使用。可以根据实际需求,灵活运用在网页开发中。