v-move指令,让元素可以随意移动,vue3+TS

1,088 阅读2分钟

缘由

还是写颜色选择器的完善,因为要有滑块功能。所以需要编写一个这么一个小东西。而且,以后页面中所有滑块都需要用到它吧。

功能我已经写完了。需要的直接拿走。非vue3的用户自己改改。

原理注意说明

当前元素会增加absolute属性,父元素会设置为relative

常规绑定

button v-dht-move="shuffle">剪切板测试</button>
function shuffle(e) {console.log(e)}

在父元素范围内移动

<button v-dht-move.boundary="shuffle">剪切板测试</button>

控制x或者y轴不能移动

以下实例x轴无法移动

<button dht-move-x="false" v-dht-move.boundary="shuffle">剪切板测试</button>

参数

参数

类型

说明

可选值

默认值

dht-move-y

string

控制是y轴是否能移动

true/false

true

dht-move-x

string

控制是x轴是否能移动

true/false

true

boundary

Boolean

是否根据父元素范围进行移动

false

回调函数

传入回调函数,得到回调返回值{ left, top, percentX, percentY }

left,top一直存在变化,会根据boundary不存在的时候是全局的的移动

存在的时候则为当前元素范围内的值

percentX, percentY为百分比值,只有boundary存在的时候进行变化

编辑器对于表格支持有问题,贴个图

代码

import { DirectiveBinding } from 'vue'

const Move = {
  // 绑定元素的父组件挂载时调用
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    const dragBox = el //获取当前元素
    const boundary = binding.modifiers?.boundary ?? false // 是否控制边界
    const callback =
      binding.value ??
      ((arg: any) => {
        return null
      })
    const x = el.getAttribute('dht-move-x') !== 'false'
    const y = el.getAttribute('dht-move-y') !== 'false'

    dragBox.style.position = 'absolute'
    const pdom = dragBox.parentNode as HTMLElement
    boundary && (pdom.style.position = 'relative')
    // 父元素宽高
    const pw = pdom.offsetWidth
    const ph = pdom.offsetHeight
    // 本身宽高
    const sw = dragBox.offsetWidth
    const sh = dragBox.offsetHeight * 2 // 在控制父边界情况下避免元素超出范围
    // 计算得到最大移动距离
    const maxw = pw - sw + dragBox.offsetLeft
    const maxh = ph - sh + dragBox.offsetHeight
    const minw = 0
    const minh = 0

    dragBox.onmousedown = (e) => {
      // 阻止默认事件,避免元素选中
      e.preventDefault()
      dragBox.style.cursor = 'move'
      //算出鼠标当前相对元素的位置
      const disX = e.x - dragBox.offsetLeft
      const disY = e.y - dragBox.offsetTop

      document.onmousemove = (e2) => {
        //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
        let left = e2.clientX - disX
        let top = e2.clientY - disY
        // 相对于父元素的移动百分比
        let percentX = 0
        let percentY = 0
        // 当传入true代表控制边界
        if (boundary) {
          left = left > maxw ? maxw : left < minw ? minw : left
          top = top > maxh ? maxh : top < minh ? minh : top
          // 计算移动百分比
          percentX = Number(((left / maxw) * 100).toFixed(2))
          percentY = Number(((top / maxh) * 100).toFixed(2))
        }

        //移动当前元素
        x && (dragBox.style.left = left + 'px')
        y && (dragBox.style.top = top + 'px')

        callback({ left, top, percentX, percentY })
      }
      document.onmouseup = (updom) => {
        //鼠标弹起来的时候不再移动
        document.onmousemove = null
        document.onmouseup = null
        dragBox.style.cursor = 'default'
      }
    }
  },
}

export default Move

关于其他功能

掘金的文章管理没有分组。所以我把我项目中可以插件化的都整理成文档了。目前在语雀。有兴趣的可以看看:

语雀随时更新:www.yuque.com/cv8igf/oy3c…

项目源码地址:github.com/ht-sauce/vi…