vue3实现一个简单拖拽组件(自定义指令)

1,144 阅读1分钟

业务需要定位一个弹窗,然后随便拖动,不需要任何特效,然后我百度了一百遍,发现没有一个简单的功能,要么是复杂的换位置,拖拽可变大小,看起来就很重,于是我觉得还不如组件用指令搞一个,就几行代码的问题,不用在安装一个npm包了,最终写下了如下的代码。这里用到一个小技巧就是js里面定义变量,在css中使用,这个功能很实用vue3才有的,然后我这边分头部是支持可拖拽的,其它部分不拖拽。

<template>
  <div v-move class="box">
    <header class="header">
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
  </div>
</template>

<script setup lang="ts">
import { Directive } from 'vue'
defineProps<{
  width: string
  height?: string
  top?: string
  left?: string
  bgColor?: string
}>()
const vMove: Directive = {
  mounted(el: HTMLElement) {
    const moveEl = el.firstElementChild as HTMLElement
    const mouseDown = (e: MouseEvent) => {
      const innerWidth = window.innerWidth - el.clientWidth
      const innerHeight = window.innerHeight - el.clientHeight
      // 鼠标点击物体那一刻相对于物体左侧边框的距离=点击时的位置相对于浏览器最左边的距离-物体左边框相对于浏览器最左边的距离
      const X = e.clientX - el.offsetLeft
      const Y = e.clientY - el.offsetTop
      const move = (e: MouseEvent) => {
        if (e.clientX - X < 0) return
        if (e.clientY - Y < 0) return
        if (e.clientX - X > innerWidth) return
        if (e.clientY - Y > innerHeight) return
        el.style.left = e.clientX - X + 'px'
        el.style.top = e.clientY - Y + 'px'
      }
      document.addEventListener('mousemove', move)
      document.addEventListener('mouseup', () => {
        document.removeEventListener('mousemove', move)
      })
    }
    moveEl.addEventListener('mousedown', mouseDown)
  }
}
</script>

<style lang="scss" scoped>
.box {
  position: fixed;
  left: v-bind(left);
  top: v-bind(top);
  width: v-bind(width);
  height: v-bind(height);
  background-color: v-bind(bgColor) ;
  border-radius: 8px;
  z-index: 1000;
  .header {
    min-height: 20px;
    cursor: move;
  }
}
</style>

使用时直接引入即可,方便快捷,在也不用加班了

import DragBox from '../../../../components/DragBox.vue'

<DragBox width="400px" top="100px" left="78%" v-show="isShowBox"></DragBox>

如果学到或者get了,麻烦贵手点下你的赞,谢谢~