手摸手教你撸一个可拖拽组件(附源码)

业务背景

1、 实现一个可以全页面可以拖拽的组件
2、顺带介绍一下vue-draggable插件,可以实现多个组件之间的拖动

展示一下效果图
在这里插入图片描述

一、可拖拽组件的封装

这个组件我是借用的vue的directive自定义指令的方式实现的,如果对vue的自定义指令还是不很熟悉的话可以先去官网了解一波,当然熟悉的童鞋也可以不用vue自定义指令来实现

1、先新建一个dragable.js文件内容如下

export default{
 bind(el, binding, vnode) {
   const dialogHeaderEl = el.querySelector('.el-dialog__header')
   const dragDom = el.querySelector('.el-dialog')
   dialogHeaderEl.style.cssText += ';cursor:move;'
   dragDom.style.cssText += ';top:0px;'

   // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
   const getStyle = (function() {
     if (window.document.currentStyle) {
       return (dom, attr) => dom.currentStyle[attr]
     } else {
       return (dom, attr) => getComputedStyle(dom, false)[attr]
     }
   })()

   dialogHeaderEl.onmousedown = (e) => {
     // 鼠标按下,计算当前元素距离可视区的距离
     const disX = e.clientX - dialogHeaderEl.offsetLeft
     const disY = e.clientY - dialogHeaderEl.offsetTop

     const dragDomWidth = dragDom.offsetWidth
     const dragDomHeight = dragDom.offsetHeight

     const screenWidth = document.body.clientWidth
     const screenHeight = document.body.clientHeight

     const minDragDomLeft = dragDom.offsetLeft
     const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth

     const minDragDomTop = dragDom.offsetTop
     const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight

     // 获取到的值带px 正则匹配替换
     let styL = getStyle(dragDom, 'left')
     let styT = getStyle(dragDom, 'top')

     if (styL.includes('%')) {
       styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
       styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
     } else {
       styL = +styL.replace(/\px/g, '')
       styT = +styT.replace(/\px/g, '')
     }

     document.onmousemove = function(e) {
       // 通过事件委托,计算移动的距离
       let left = e.clientX - disX
       let top = e.clientY - disY

       // 边界处理
       if (-(left) > minDragDomLeft) {
         left = -minDragDomLeft
       } else if (left > maxDragDomLeft) {
         left = maxDragDomLeft
       }

       if (-(top) > minDragDomTop) {
         top = -minDragDomTop
       } else if (top > maxDragDomTop) {
         top = maxDragDomTop
       }

       // 移动当前元素
       dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`

       // emit onDrag event
       // vnode.child.$emit('dragDialog')
     }

     document.onmouseup = function(e) {
       document.onmousemove = null
       document.onmouseup = null
     }
   }
 }
}

2、新建dragFrame.vue组件,内容如下:

<template>
  <div v-dragable>
    <div class="el-dialog">
      <div class="el-dialog__header">我是可拖拽组件</div>
      <slot></slot>
    </div>
  </div>
</template>
<script>
import dragable from "@/common/directive/dragable"; // 引入指令js文件
export default {
  name: "dragFrame",
  directives: { dragable }, // 注册指令
  data() {
    return {};
  }
};
</script>


3、在页面中使用组件, 代码如下:

在这里插入图片描述

二、vue-draggable插件的使用

vuedraggable组件非常强大,大家可以自己去官网学习。这里就不多说了!

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页