【Vue】vue3 v-draggable 拖拽指令封装

说明

需求:实现一个拖拽指令,可在父元素区域任意拖拽元素,同时如果传入的值为 father,则拖拽的时候以父元素为拖拽对象

思路:
1、设置需要拖拽的元素为absolute,其父元素为relative。
2、鼠标按下(onmousedown)时记录目标元素当前的 left 和 top 值。
3、鼠标移动(onmousemove)时计算每次移动的横向距离和纵向距离的变化值,并改变元素的 left 和 top 值
4、鼠标松开(onmouseup)时完成一次拖拽

使用:在 Dom 上加上 v-draggable 即可
<div class="dialog-model" v-draggable></div>

代码

import type { Directive, DirectiveBinding } from 'vue';
interface ElType extends HTMLElement {
  parentNode: any;
}
const draggable: Directive = {
  mounted: function (el: ElType, binding: DirectiveBinding) {
    el.style.cursor = 'move';
    el.style.position = 'absolute';
    el.onmousedown = function (e) {
      let disX = e.pageX - el.offsetLeft;
      let disY = e.pageY - el.offsetTop;

      if (binding.value === 'father') {
        disX = e.pageX - el.parentNode.offsetLeft;
        disY = e.pageY - el.parentNode.offsetTop;
      } else {
        disX = e.pageX - el.offsetLeft;
        disY = e.pageY - el.offsetTop;
      }

      document.onmousemove = function (e) {
        let x = e.pageX - disX;
        let y = e.pageY - disY;
        let maxX;
        let maxY;

        if (binding.value === 'father') {
          maxX =
            el.parentNode.parentNode.offsetWidth - el.parentNode.offsetWidth;
          maxY =
            el.parentNode.parentNode.offsetHeight - el.parentNode.offsetHeight;
        } else {
          maxX = el.parentNode.offsetWidth - el.offsetWidth;
          maxY = el.parentNode.offsetHeight - el.offsetHeight;
        }

        if (x < 0) {
          x = 0;
        } else if (x > maxX) {
          x = maxX;
        }

        if (y < 0) {
          y = 0;
        } else if (y > maxY) {
          y = maxY;
        }

        if (binding.value === 'father') {
          el.parentNode.style.left = x + 'px';
          el.parentNode.style.top = y + 'px';
        } else {
          el.style.left = x + 'px';
          el.style.top = y + 'px';
        }
      };
      document.onmouseup = function () {
        document.onmousemove = document.onmouseup = null;
      };
    };
  },
};
export default draggable;

演示

      <!-- 详情弹窗 -->
      <transition name="fade">
        <div class="entity-detail-box" v-if="isShowDetail" :style="detailStyle">
          <div v-draggable="'father'" class="drag-mask"></div>
          <div class="closeBtn pointer" @click="() => (isShowDetail = false)">
            关闭
          </div>
          <slot name="detail"></slot>
        </div>
      </transition>

在这里插入图片描述

vue-draggable的原理是基于sortable.js插件来实现的。sortable.js是一个根据DOM操作实现拖拽功能的插件,而vue-draggable作为一个针对Vue框架的插件,将sortable.js和Vue的数据驱动视图结合起来。 vue-draggable利用Vue的组件化特性,将sortable.js的拖拽功能封装成一个可复用的Vue组件。通过在Vue组件中使用vue-draggable,我们可以直接在Vue的模板中使用拖拽功能,而无需直接操作DOM。 具体实现原理是通过监听用户的拖拽操作,然后更新Vue组件中的数据,从而实现对数据的排序和更新。当用户拖拽某个元素时,vue-draggable会根据sortable.js的回调函数,更新Vue组件中的数据,然后重新渲染视图。 总结来说,vue-draggable通过将sortable.js和Vue的数据驱动视图结合起来,实现了在Vue框架中使用拖拽功能的原理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [vue-draggable-resizable伸缩antdv的a-table表格列时components等数据的写法](https://blog.csdn.net/renovateF5/article/details/124591971)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [浅谈vue-draggable原理](https://blog.csdn.net/weixin_43160044/article/details/127349586)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值