Vue3为dom组件增加 自定义可拖拽改变大小的指令(属性)

发布时间 2023-04-12 18:10:39作者: 虚无——缥缈

添加如下js文件resizable.js:

 1 // 支持上下左右四边拖动。若内部元素太贴边,不易触发拖动事件,最好在拖动一边加边框,使鼠标容易选中。
 2 // 使用方式:
 3 // <div v-resizable="'right, bottom'">
 4 export default {
 5   install: (app) => {
 6     const sideArr = ['right', 'left', 'top', 'bottom']
 7     const errmsg = 'resizable needs string value of: ' + sideArr
 8     const minSize = 40
 9     const dragSize = 5
10 
11     app.directive('resizable', {
12       mounted(el, binding, vnode, oldVnode) {
13         const dragable = {}
14         const oriCur = el.style.cursor
15         const sides = binding.value.replace(' ', '').split(',')
16         let dragSide = ''
17         let dragging = false
18 
19         if (sides.length === 0) {
20           throw errmsg
21         }
22         for (let i = 0; i < sides.length; i++) {
23           if (sideArr.indexOf(sides[i]) < 0 ) {
24             throw errmsg
25           }
26           dragable[sides[i]] = true
27         }
28 
29         el.addEventListener('mousemove', (e) => {
30           if (dragging) return
31 
32           if (dragable['right'] && el.offsetWidth - e.offsetX < dragSize) {
33             el.style.cursor = 'ew-resize'
34             dragSide = 'right'
35           }
36           else if (dragable['left'] && e.offsetX < dragSize) {
37             el.style.cursor = 'ew-resize'
38             dragSide = 'left'
39           }
40           else if (dragable['top'] && e.offsetY < dragSize) {
41             el.style.cursor = 'ns-resize'
42             dragSide = 'top'
43           }
44           else if (dragable['bottom'] && el.offsetHeight - e.offsetY < dragSize) {
45             el.style.cursor = 'ns-resize'
46             dragSide = 'bottom'
47           }
48           else {
49             el.style.cursor = oriCur
50             dragSide = ''
51           }
52         })
53 
54         el.addEventListener('mousedown', (e) => {
55           if ( !dragSide ) return
56 
57           dragging= true
58           const cstyle = window.getComputedStyle(el)
59           const width = Number.parseInt(cstyle.width)
60           const height = Number.parseInt(cstyle.height)
61           const elW = width > 0 ? width : el.offsetWidth
62           const elH = height > 0 ? height : el.offsetHeight
63           const clientX = e.clientX
64           const clientY = e.clientY
65 
66           const movefun = (e) => {
67             e.preventDefault()
68             if (dragSide === 'right' && (e.clientX > clientX || el.offsetWidth >= minSize)) {
69               el.style.width = elW + (e.clientX - clientX) + 'px'
70             }
71             else if (dragSide === 'left' && (e.clientX < clientX || el.offsetWidth >= minSize)) {
72               el.style.width = elW + (clientX - e.clientX) + 'px'
73             }
74             else if (dragSide === 'top' && (e.clientY < clientY || el.offsetHeight >= minSize)) {
75               el.style.height = elH + (clientY - e.clientY) + 'px'
76             }
77             else if (dragSide === 'bottom' && (e.clientY > clientY || el.offsetHeight >= minSize)) {
78               el.style.height = elH + (e.clientY - clientY) + 'px'
79             }
80           }
81           const removefun = () => {
82             dragging= false
83             document.removeEventListener('mousemove', movefun)
84             document.removeEventListener('mouseup', removefun)
85           }
86 
87           document.addEventListener('mousemove', movefun)
88           document.addEventListener('mouseup', removefun) 
89         })
90       }
91     })
92   }
93 }

main.js中应用它:

1 //引入
2 import resizable from '@/directive/resizable'
3 
4 const app = createApp(App)
5 app.use(resizable)

在组件属性中就只可以设置了,比如,右边和下边都可以拖拽改变大小:

1 <div v-resizable="'right, bottom'">
2 </div>

引用自:https://www.jianshu.com/p/adef837a3d3a