vben中通过自定义指令 实现边界拖拽
注意: 当前写法是在vben中实现 若使用其他前端模板 只需要更改第二步 注册方式即可
问题描述:项目中经常遇到某些上下结构或者左右结构的排版 其中某些元素需要边界拖拽以实现其他元素的展示
常见场景:业务上需要是左树右列表的页面 树节点title过长时无法全部展示 通过边界拖拽 可以更友好的展示树节点的信息
第一步 创建边界拖拽自定义指令文件
文件地址:src\directives\dragResize.ts
importtype{Directive,App}from'vue';constdragResizeDirective:Directive={mounted(el:HTMLElement,binding){constsideArr=['right','left','top','bottom'];constminSize=binding.value?.minSize||100;constmaxSize=binding.value?.maxSize||1000;constdragSize=5;constoriCur=el.style.cursor;// 解析需要拖拽的边constsides=binding.value?.replace(/\s/g,'').split(',')||['right'];constdragable:Record<string,boolean>={};for(constsideofsides){if(!sideArr.includes(side)){thrownewError('resizable needs string value of: '+sideArr);}dragable[side]=true;}letdragSide='';letdragging=false;// 辅助函数:获取鼠标相对于 el 的坐标constgetMousePos=(e:MouseEvent)=>{constrect=el.getBoundingClientRect();return{x:e.clientX-rect.left,y:e.clientY-rect.top,width:rect.width,height:rect.height,};};el.addEventListener('mousemove',(e:MouseEvent)=>{if(dragging)return;const{x,y,width,height}=getMousePos(e);if(dragable.right&&width-x<dragSize){el.style.cursor='col-resize';dragSide='right';}elseif(dragable.left&&x<dragSize){el.style.cursor='col-resize';dragSide='left';}elseif(dragable.top&&y<dragSize){el.style.cursor='row-resize';dragSide='top';}elseif(dragable.bottom&&height-y<dragSize){el.style.cursor='row-resize';dragSide='bottom';}else{el.style.cursor=oriCur;dragSide='';}});el.addEventListener('mousedown',(e:MouseEvent)=>{if(!dragSide)return;dragging=true;const{width,height}=getMousePos(e);constelW=width;constelH=height;constclientX=e.clientX;constclientY=e.clientY;constmovefun=(e:MouseEvent)=>{e.preventDefault();if(dragSide==='right'&&(e.clientX>clientX||el.offsetWidth>=minSize)){constnewWidth=elW+(e.clientX-clientX);el.style.width=Math.min(newWidth,maxSize)+'px';}elseif(dragSide==='left'&&(e.clientX<clientX||el.offsetWidth>=minSize)){constnewWidth=elW+(clientX-e.clientX);el.style.width=Math.min(newWidth,maxSize)+'px';}elseif(dragSide==='top'&&(e.clientY<clientY||el.offsetHeight>=minSize)){constnewHeight=elH+(clientY-e.clientY);el.style.height=Math.min(newHeight,maxSize)+'px';}elseif(dragSide==='bottom'&&(e.clientY>clientY||el.offsetHeight>=minSize)){constnewHeight=elH+(e.clientY-clientY);el.style.height=Math.min(newHeight,maxSize)+'px';}};constremovefun=()=>{dragging=false;document.removeEventListener('mousemove',movefun);document.removeEventListener('mouseup',removefun);};document.addEventListener('mousemove',movefun);document.addEventListener('mouseup',removefun);});},};exportfunctionsetupDragResizeDirective(app:App){app.directive('drag-resize',dragResizeDirective);}exportdefaultdragResizeDirective;第二步 在统一自定义指令注册ts中注册边界拖拽指令
文件地址:src\directives\index.ts
或:参考 vue官网自定义指令 注册全局自定义指令
第三步 使用
在需要使用边界指令的元素上添加 v-drag-resize
<divstyle="display: flex"><div v-drag-resize>树</div><divstyle="flex: 1">列表</div></div>注意:
- 将其父元素设置成弹性盒模型
- 给其兄弟元素设置属性flex: 1
