Vue3为dom组件增加 自定义可拖拽改变大小的指令(属性)
添加如下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>