首页 > 其他分享 >【Vue】vue3 v-draggable 拖拽指令封装

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

时间:2023-08-29 11:56:40浏览次数:49  
标签:el style Vue maxX parentNode draggable let vue3 拖拽

说明

需求:实现一个拖拽指令,可在父元素区域任意拖拽元素,同时如果传入的值为 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>

在这里插入图片描述

标签:el,style,Vue,maxX,parentNode,draggable,let,vue3,拖拽
From: https://www.cnblogs.com/wx980416/p/17664379.html

相关文章

  • 【Vue】vue3 中 如何将el-table的表格数据下载为.xlsx格式文件
    安装依赖首先,你需要安装xlsx和file-saver这两个库。npminstallxlsxfile-saver--save有兴趣可以看看两个库的官方说明,直接看下面使用也没问题。xlsx官方介绍TheSheetJSCommunityEditionoffersbattle-testedopen-sourcesolutionsforextractingusefuldata......
  • Vue3 Refs模板
    Refs模板用来获取页面DOM元素或者组件,类似于Vue2.X中的$refs。Refs模板的使用方法如下。(1)在setup()中创建ref对象,其值为null。(2)为元素添加ref属性,其值为步骤(1)中创建的ref对象名。(3)完成页面渲染之后,获取DOM元素或者组件。 src\views\HomeView.vue<template><d......
  • Vue3 依赖注入 provide() inject()
    依赖注入就是父组件向后代组件传递数据,可以向子组件传递数据,也可以向孙子组件传递数据。在父组件中使用provide()函数,向后代传递数据。在后代组件中使用inject()函数,获取传递过来的数据。 provide()​提供一个值,可以被后代组件注入。inject()​注入一个由祖先组件或整个应......
  • vue~el-autocomplete实现组件化
    el-autocomplete核心参数可以实现异步的数据拉取,从异步返回的数据中,选择需要的结果,并回显到文本框中。fetch-suggestions回调列表,异步的方式获取数据列表,显示在列表框中@select当选中某一项时,会触发这个方法,将数据获取到,这时,我们可以将数据回显,或者赋值给父页面上的元素,如果......
  • Vue3 watch() 监听
    watch()​侦听一个或多个响应式数据源,并在数据源变化时调用所给的回调函数 <template> <span> <p>{{num}}</p> <p>{{num2}}</p> <button@click="num++">+1</button> <button@click="addNum">+1</button> &......
  • Vscode如何如何显示vue代码提示
    Vscode使用版本 下载这个插件 ......
  • vue3 setup访问子组件的 DOM 元素
    使用setup的情况下这个时候我们无法使用this,注意在setup中setup是封闭的,不会将子组件事件暴露出来,所以要用defineExpose(),将需要在父组件调用的函数暴露出去,子组件代码如下:<template><divref="domRef"><div>哈哈哈哈</div></div></template><scriptsetuplang="t......
  • Vue3 computed() 计算属性
      <template> <span> <p>普通属性:{{num}}</p> <p>计算属性-只读:{{numAdd}}</p> <p>计算属性-可读写:{{numAdd2}}</p> <button@click="numUpdate">修改普通属性</button> <button@click="numAddUpda......
  • vue--day74--四个map方法的使用mapState ,mapGetters,mapMutations,mapActions
    1.Count.vue<template><div><h1>当前求和位{{sum}}</h1><h1>当前求和放大10倍后是{{bigSum}}</h1><h1>我在{{school}},学习{{subject}}</h1><selectv-model.number="n"><optionva......
  • vue3 + vite 动态引入不被打包的静态资源
    在开发中,通常会把一些静态资源放在assets文件夹下,但是assets目录下的内容是需要vite编译打包的,所以如果只是引用assets目录下的资源时,使用绝对路径、相对路径均可。但是,在开发中,我们经常会引用一些不被打包的资源,此时该资源是放在public目录下的,那么在引用时,路径的写法如下:不......