需求是这样的:需要将目前的el-dialog弹窗都改成可拉伸和拖拽的。并且做自适应。(一番交涉下来,最终是如果弹窗里面有table的话,我们给table的高度自适应,普通表单不需要)。

确定了需求,准备开发,在网上找了一圈,大家的都差不多,所以我在他们的基础上加了一些自己的改动。说说目前网上其他我搜到的文件用在我们的项目的问题:1.拖动的时候到处飞,没有加边界条件。 2.可以把弹窗拉的非常小,以至于出现滚动条之后,右侧再无法拉伸。3.使用了拉伸的方法后,弹窗内的form表单无法进行拖拽选中input内的文字。

针对上面几个问题,改了些地方。一起来写吧!

1.开始自定义指定

从别人的文档“借鉴”过来的自定义指令外壳。将几个方法都拿出来当方法了。(公司要求方法行数不能大于50行_(:з」∠)_,只能硬拆)

import Vue from 'vue';
// v-dialogDrag: 弹窗拖拽属性
Vue.directive('dialogDrag', {bind(el, binding, vnode, oldVnode) {// 弹框可拉伸最小宽高,不设置的话,会导致出现滚动条无法进行拉伸。let minWidth = 620let minHeight = 370// 获取弹框头部const dialogHeaderEl = el.querySelector('.dialog_header');// 获取弹窗const dragDom = el.querySelector('.el-dialog')// 给弹窗加上overflow:auto;不然缩小时框内的标签可能超出dialog   dragDom.style.overflow = 'auto'// 头部加上可拖动cursordialogHeaderEl.style.cursor = 'move'// 头部拖拽dialogHeaderEl.onmousedown = (e) => {moveDown(e,dialogHeaderEl,dragDom)},document.onmousemove = function (e) {// 获取弹窗的边界位置值let domRect = dragDom.getBoundingClientRect()let endX =e.clientX,endY=e.clientY// 获取鼠标在边角的样式。头部因为有拖拽事件,所以无法拉伸。 cursorType(e,el,dragDom)// 不在弹窗 - 10px 的内部,才走这些方法。防止拉伸事件影响表单选中文本if(isBorder(domRect,{endX,endY})){dragDom.onmousedown = e =>{const initHeight = dragDom.clientHeightconst clientX = e.clientX // clientX事件属性返回当事件被触发时相对于浏览器页面(或客户区)的水平坐标const clientY = e.clientYlet elW = dragDom.clientWidthlet elH = dragDom.clientHeightlet EloffsetLeft = dragDom.offsetLeftlet EloffsetTop = dragDom.offsetTop dragDom.style.userSelect = 'text'let ElscrollTop = el.scrollTop// 判断点击的位置是不是为头部if (clientX > EloffsetLeft &&clientX < EloffsetLeft + elW &&clientY > EloffsetTop &&clientY < EloffsetTop + 100) {// 如果是头部在此就不做任何动作,以上有绑定dialogHeaderEl.onmousedown = moveDown;} else {let diffX = endX - clientX,diffY = endY - clientYdocument.onmousemove = e => mousemove(e,dragDom,clientX,EloffsetLeft,elW,minWidth,ElscrollTop,clientY,EloffsetTop,elH,minHeight,diffX,diffY)// 拉伸结束isOver(dragDom,minHeight,initHeight)}}}}}
})

2.弹窗头部拖拽事件

弹窗头部拖拽事件单独拿出来写。加上边界条件。不然弹窗拖到莫名其妙地方去啦~

   // 弹窗头部拖拽事件function moveDown(e,dialogHeaderEl,dragDom){let dialogW = 0 //鼠标按下,计算当前元素的大小let dialogH = 0let pageW = document.documentElement.clientWidth // 页面宽度let pageH = document.documentElement.clientHeight //页面高度// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)// 鼠标按下,计算当前元素距离可视区的距离const disX = e.clientX - dialogHeaderEl.offsetLeftconst disY = e.clientY - dialogHeaderEl.offsetTop// 对话框宽高dialogW = dragDom.offsetWidthdialogH = dragDom.offsetHeightconst minDragDomLeft = dragDom.offsetLeftconst maxDragDomLeft = pageW - dragDom.offsetLeft - dialogWconst minDragDomTop = dragDom.offsetTopconst maxDragDomTop = pageH - dragDom.offsetTop - dialogH// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为pxif (sty.left.includes('%')) {styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)} else {styL = +sty.left.replace(/\px/g, '')styT = +sty.top.replace(/\px/g, '')}document.onmousemove = function(e) {// 通过事件委托,计算移动的距离let left = e.clientX - disXlet top = e.clientY - disY// 边界处理if (-(left) > minDragDomLeft) {left = -(minDragDomLeft)} else if (left > maxDragDomLeft) {left = maxDragDomLeft}if (-(top) > minDragDomTop) {top = -(minDragDomTop)} else if (top > maxDragDomTop) {top = maxDragDomTop}// 移动当前元素dragDom.style.left = `${left + styL}px`dragDom.style.top = `${top + styT}px`// 鼠标抬起停止弹窗移动document.onmouseup = function () {document.onmousemove = nulldocument.onmouseup = null}}}

3.鼠标的样式判断方法

因为头部有拖拽事件了,所以无法再拉伸,我们只在左右,左下角和右下角添加拉伸的样式

 function cursorType(e,el,dragDom){if(dragDom.offsetTop + dragDom.clientHeight - 10 < e.clientY &&e.clientY < dragDom.offsetTop + dragDom.clientHeight && dragDom.offsetLeft < e.clientX && e.clientX < dragDom.offsetLeft + 10){dragDom.style.cursor = 'sw-resize' // 左下}else if (dragDom.offsetLeft + dragDom.clientWidth - 10 < e.clientX &&e.clientX < dragDom.offsetLeft + dragDom.clientWidth && dragDom.offsetTop +dragDom.clientHeight - 10 < e.clientY &&e.clientY < dragDom.offsetLeft + dragDom.clientHeight){dragDom.style.cursor = 'se-resize' // 右下} else if (e.clientX > dragDom.offsetLeft + dragDom.clientWidth - 10 ||dragDom.offsetLeft + 10 > e.clientX){dragDom.style.cursor = 'w-resize' // 左}else if (el.scrollTop + e.clientY > dragDom.offsetTop + dragDom.clientHeight -10){dragDom.style.cursor = 's-resize' // 右}else{dragDom.style.cursor = 'default'dragDom.onmousedown = null}}

4.鼠标拖拽弹窗,左拉右拉

拉伸弹窗,左拉和右拉,只要一个拉伸,左右都会同时放大。这里可以根据各自需求去改就行。如果不需要同时放大,在这个方法里改

 function mousemove(e,dragDom,clientX,EloffsetLeft,elW,minWidth,ElscrollTop,clientY,EloffsetTop,elH,minHeight,diffX,diffY){// 移动时禁用默认事件e.preventDefault()// 左侧鼠标拖拽位置if (clientX > EloffsetLeft && clientX < EloffsetLeft + 10) {// 往左拖拽if (clientX > e.clientX) {dragDom.style.width = elW + (clientX - e.clientX) * 2 + 'px'}// 往右拖拽if (clientX < e.clientX) {if (dragDom.clientWidth < minWidth) {// 设置最小宽度,不能无限缩小,滚动条会让弹窗无法拉伸dragDom.style.width = minWidth} else {dragDom.style.width = elW - (e.clientX - clientX) * 2 + 'px'}}}// 右侧鼠标拖拽位置if (clientX > EloffsetLeft + elW - 10 && clientX < EloffsetLeft + elW) {// 往左拖拽if (clientX > e.clientX) {if (dragDom.clientWidth < minWidth) {dragDom.style.width = minWidth} else {dragDom.style.width = elW - (clientX - e.clientX) * 2 + 'px'}}// 往右拖拽if (clientX < e.clientX) {dragDom.style.width = elW + (e.clientX - clientX) * 2 + 'px'}}// 底部鼠标拖拽位置if (ELscrollTop + clientY > EloffsetTop + elH - 20 &&ELscrollTop + clientY < EloffsetTop + elH) {// 往上拖拽if (clientY > e.clientY) {if (dragDom.clientHeight < minHeight) {// 设置最小高度,不能无限缩小,滚动条会让弹窗无法拉伸dragDom.style.height = minHeight} else {dragDom.style.height = elH - (clientY - e.clientY) * 2 + 'px'}}// 往下拖拽if (clientY < e.clientY) {boundaryLimit('bottom',dragDom,diffX,diffY,elH,clientY)}}}

5.校验鼠标移动的位置是否在弹窗边缘

这里多说几句,因为指令写的拉伸事件,导致整个弹窗的onmousedown事件都跟拉伸挂钩。所以导致弹窗中表单无法onmousedown去选中文字复制。这里2个思路都可以实现:A:在4事件里,就是拖拽事件里,判断如果不是在边界上拖拽,就阻止冒泡事件,不让弹窗拉伸的事件和表单选中input框文字的事件起冲突。 B:就是我写的这个方法,做一个判断条件,如果在弹窗边缘,才可以走拉伸的事件。 方法很多,大家可以自己试试!

 // 校验鼠标移动的位置是否在弹窗边缘function isBorder(domRect,cursorPosition){let left = domRect.left,right = domRect.right,top = domRect.top,bottom = domRect.bottom,cursorX = cursorPosition.endX,cursorY = cursorPosition.endYif((left > cursorX - 10 && left <cursorX + 10) || (right > cursorX -10 && right < cursorX +10) ||(top > cursorY -10 && top < cursorY + 10) ||(bottom > cursorY - 10 && bottom < cursorY + 10)){return true} else {return false} }

6.鼠标拉伸结束,该让一切消失了

 // 鼠标拉伸结束function isOver(dragDom,minHeight,initHeight){document.onmouseup = function(e){// 防止拉伸高度太短,导致滚动条,所以这里必须再设置一次最小高度if(dragDom.clientHeight <= minHeight){dragDom.style.height = minHeight + 'px'}/* 给弹窗里的table添加上 ‘drag-flex-table’类名,表示拖拽的弹窗里表格需要自适应。动态给table设置高度。这里只适用于弹窗只有一个table,如果多个table,还需要根据实际情况进行适当更改*/if(dragDom.querySelector('.drag-flex-table')){const elem = dragDom.querySelector('.drag-flex-table')let tableHeight = dragDom.clientHeight - initHeight + elem.clientHeight// 36px在这里是table的theader的高度,我们给table_body去设置elem.style.height = `${tableHeight - 36}px`}document.onmousemove = nulldocument.onmouseup = null}}

7.差点忘记还有一个拉伸边界条件!

这里只写了一个下拉的边界条件。虽然也是有点问题的。但是无伤大雅了!

 // 拉伸的边界条件function boundaryLimit(type,dragDom,diffX,diffY,elH,clientY){const screenHeight = document.documentElement.clientHeight || document.body.clientHeightif(type == 'bottom'){if(diffX + dragDom.clientHeight > screenHeight - dragDom.offsetTop){dragDom.style.height = screenHeight - dragDom.offsetTop}else{dragDom.style.height = elH + (e.clientY -clientY) + 'px'}}}

综上,一个可拖拽并且可拉伸,还加了边界条件的自定义指令结束了。使用方法,同其他自定义指令一样,在el-dialog上添加自定义指令。如果弹窗里有需要自适应的table,给这个table添加'drag-flex-table'类名就行!如果大家有更好的写法,欢迎在评论区告诉我!

vue+element弹窗可拖拽拉伸和弹窗内table高度自适应相关推荐

  1. Vue Element 表格实现拖拽排序

    1.安装sortablejs npm install sortablejs --save 2.在需要的页面引入 import Sortable from 'sortablejs' 3.具体使用,注意的 ...

  2. element 弹窗 实现拖拽 放大 拉伸

    element 弹窗 实现拖拽 放大 拉伸 自定义一个指令,下方代码直接使用,针对的是element 弹窗 使用:直接引入js, 在el-dialog上只是使用v-dialogDrag 就可以了,斜角 ...

  3. Vue.Draggable 实现组件拖拽

    Vue.Draggable 实现组件拖拽 特性 支持触摸设备 支持拖拽和选择文本 支持智能滚动 支持不同列表之间的拖拽 不以jQuery为基础 和视图模型同步刷新 和vue2的国度动画兼容 支持撤销操 ...

  4. Android仿探探卡片拖拽,Vue 仿探探拖拽卡片的效果

    原标题:Vue 仿探探拖拽卡片的效果 已更新Vue3版,请给前端大全发送关键字vue3仿探探获取Vue3版 类似 Tinder 和 探探 的卡片效果的组件,社区中已经非常多了.我这一版除了可以实现和他 ...

  5. vue+sortable实现表格拖拽

    vue+sortable实现表格拖拽 前言: 支持 vue3.0 支持表格拖拽 支持自定义拖拽 sortable官网 一.下载 sortable npm install sortablejs --sa ...

  6. Vue+el-tree,元素拖拽时出现禁用图标, 请看解决办法

    项目需求:vue+el-tree实现节点拖拽到指定div播放视频: 问题:当节点拖拽时, 出现禁用图标: 一开始以为将禁用图标改变样式或隐藏就可以,一番尝试后, 发现这个图标可能是浏览器默认的, 经过 ...

  7. AE 超人飞天特效 地面震裂崩飞效果 。SU 可以快速建立模型。室内室外。通过将CAD 的图拖拽 拉伸成面

    今天完成 工资结算发放. 继续TX PDF AE 超人飞天特效  地面震裂崩飞效果 人中枪弹爆头效果 需要相关素材, 比如地面震裂 崩飞 的素材 枪弹 的血液飞溅的素材等 跟踪,动态模糊,快速模糊, ...

  8. 基于 Spring Boot + Vue 实现的可视化拖拽编辑的大屏项目

    大家好,今天给小伙伴们分享一个基于 SpringBoot + Vue 实现的可视化拖拽编辑的大屏项目: 简介 这个是一个开源的一个BI平台,酷炫大屏展示,能随时随地掌控业务动态,让每个决策都有数据支撑 ...

  9. vue 自定义指令弹窗鼠标拖拽弹窗表头,弹窗移动

    拖拽整个过程由三个事件完成 鼠标按下事件 onmousedown 鼠标移动事件 onmousemove 鼠标抬起事件 onmouseup Vue.directive('drag', {inserted ...

最新文章

  1. EXTJS之Ext.util.Observable自定义事件
  2. asp.net在线人数限制
  3. C# 线程手册 第三章 使用线程
  4. Java--Servlet,@ServletSecurity,role,username,password
  5. flask 必知必会
  6. 编写JQuery插件-2
  7. Spring-boot快速实现Spring框架配置
  8. SQL数据库只读问题
  9. 利用openpyxl来读取Excel数据
  10. go 获取内核数_Go的GPM多线程调度
  11. junit 生成html报告,gradle – 如何为JUnit 5测试创建HTML报告?
  12. 毕设题目:Matlab优化分配
  13. java在线答疑系统_网上学习和答疑系统系统
  14. 整理一下CCF推荐期刊会议(A类)
  15. 关于html5小游戏的书,HTML5小游戏:書道 - 书法之境 道之升华
  16. python psutil 汇总 tcy
  17. 在ESC云服务器中部署KodCloud云盘系统(四)
  18. Java修改图片元数据Exif信息
  19. windows启用Guest用户
  20. sam卡和sim卡区别_SAM卡

热门文章

  1. 最小公倍数C语言怎么算,算法:最大公约数和最小公倍数(C语言表示)
  2. java数组首尾互换,c语言程序,将一个数组首尾互换后输出
  3. FastAPI(55)- Events: startup - shutdown 启动/关闭事件
  4. oracle增加分区时报ora14036,增加分区表2009年的分区报ORA-14074错误
  5. 微信开发者解除绑定微信公众号的方法,亲测有效
  6. C#导入Excel数据(简单)
  7. Coco2d-x 3.x : Cocos Studio 制作的UI无法正确显示,出现绿色或白色底
  8. 数据压缩作业:LZW词典编码
  9. postMan请求结果中文乱码
  10. 手把手教你搭建惊艳的博客