【Vue3】自定义拖拽指令并阻止点击事件

自定义拖拽指令

悬浮可拖拽组件的实现涉及到鼠标事件的应用,为了提高代码可复用性,本文将拖拽功能的实现封装为Vue指令,可通过全局引用直接调用。

src/utils/目录下新建drag.ts

const drag = {
  beforeMount(el: any) {
    el.style.cursor = "move";

    el.onmousedown = (e: any) => {
      const mouseX = e.clientX;
      const mouseY = e.clientY;
      const domX = el.offsetLeft;
      const domY = el.offsetTop;
      const maxX = document.body.clientWidth - el.offsetWidth;
      const maxY = document.documentElement.clientHeight - el.offsetHeight;

      document.onmousemove = function (e) {
        const deltaX = e.clientX - mouseX;
        const deltaY = e.clientY - mouseY;
        let newX = domX + deltaX;
        let newY = domY + deltaY;

        //边界控制
        if (newX < 0) newX = 0;
        else if (newX > maxX) newX = maxX;
        if (newY < 0) newY = 0;
        else if (newY > maxY) newY = maxY;

        el.style.left = newX + "px";
        el.style.top = newY + "px";
      };

      document.onmouseup = function () {
        document.onmousemove = null;
        document.onmouseup = null;
      };
      return false;
    };
  },
};

const directives = {
  install: function (app: any) {
    app.directive("drag", drag);
  },
};
export default directives;

src/main.ts中引入该指令:

import drag from "@/utils/drag";
app.use(drag)

给要拖拽的节点添加v-drag属性,同时在style中设置position: fixed

<template>
  <div class="dragDiv" v-drag="true"> ... </div>
</template>

<style>
.dragDiv {
  position: fixed;
  width: 50px;
  height: 50px;
  right: 10px;
  bottom: 10px;
  z-index: 10;
}
</style>

阻止点击事件

拖拽动作涉及mousedownmousemovemouseup事件,而mousedownmouseup又会触发click事件。触发顺序:mousedownmousemovemouseupclick

如果给click事件绑定了函数,如点击打开对话框,那么在拖拽该组件后也会触发对应的click操作,这往往是我们不希望的,所以需要区分开拖拽和click,阻止click的执行。

实现思路:在mousemove事件触发时,给组件添加“拖拽”标记,当click事件触发时,先检查该标记以决定是否继续执行。

在拖拽指令的基础上进行修改:

el.onmousedown = (e: any) => {
  //拖拽标记还原
  el.dragFlag = false;
  ...
  document.onmousemove = function (e) {
    //设置拖拽标记
    el.dragFlag = true;
    ...
  }
  ...
}

在组件的click处理函数中添加dragFlag标记判断:

<template>
  <div ref="dragRef" class="dragDiv" v-drag="true" @click="handleClick">...</div>
</template>

<script lang="ts" setup>
import { ref } from "vue";
const dragRef = ref(null);
function handleClick() {
  //如果是拖拽,则不运行后续代码
  if (dragRef.value.dragFlag) return;
  ...
}
</script>

参考

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值