ElementUI的el-dialog弹窗修改设置可拖拽可最大化

简介: 该方案通过自定义Vue指令实现ElementUI的`el-dialog`弹窗的拖拽和最大化功能。只需在`main.js`中引入并注册指令,然后在Vue组件中绑定指令即可。支持自定义参数控制是否允许最大化和拖拽,并提供最大化后的回调函数。具体使用方法详见示例代码。

ElementUI的el-dialog弹窗怎么设置可拖拽,可最大化

可直接自定义一条vue指令,vue页面直接绑定指令即可完成。

效果图如下:
dialog-20240918.gif

```javascript
export default {
  bind(el, binding, vnode, oldVnode) {
    //初始非全屏
    let isFullScreen = false;
    //当前宽高
    let nowWidth = 0;
    let nowHeight = 0;
    //当前顶部高度
    let nowMarginTop = '0';
    //获取弹框头部(这部分可双击全屏)
    const dialogHeaderEl = el.querySelector('.el-dialog__header');
    let hasSetBodyHeight = false;
    //弹窗
    const dragDom = el.querySelector('.el-dialog');
    //给弹窗加上overflow auto;不然缩小时框内的标签可能超出dialog;
    // dragDom.style.overflow = "auto";
    //清除选择头部文字效果
    dialogHeaderEl.onselectstart = new Function("return false");
    // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
    const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
    //头部插入最大化最小化元素
    let maxMin = document.createElement("button");
    maxMin.className += ' el-dialog__headerbtn el-dialog__minmax';
    maxMin.style.right = '40px';
    maxMin.style.color = '#409eff';
    maxMin.title = '最大化';
    maxMin.innerHTML =
      '<i class="el-icon-full-screen" style="font-size: 16px; display: block; margin: 3px;" onMouseOver="this.style.color=\'#e94646\'" onMouseOut="this.style.color=\'#409eff\'"></i>';
    dialogHeaderEl.insertBefore(maxMin, dialogHeaderEl.childNodes[1]);
    let cls = dialogHeaderEl.childNodes[2];
    let bodyHeight = 'auto';

    // 窗口-最大化与还原
    function setMaxMin() {
      isFullScreen = !isFullScreen;
      if (isFullScreen) {
        let i = maxMin.querySelector('.el-icon-full-screen');
        i.classList.remove('el-icon-full-screen');
        i.classList.add('el-icon-crop');
        maxMin.title = '还原';
        bodyHeight = dragDom.querySelector('.el-dialog__body').offsetHeight + 'px';
        nowWidth = dragDom.clientWidth;
        nowHeight = dragDom.clientHeight;
        nowMarginTop = dragDom.style.marginTop;
        dragDom.style.left = 0;
        dragDom.style.top = 0;
        dragDom.style.height = "100VH";
        dragDom.style.width = "100VW";
        dragDom.style.margin = "0 auto";
        dragDom.style.borderRadius = '0';
        // dialogHeaderEl.style.cursor = 'initial';
        if (!hasSetBodyHeight) {
          dragDom.querySelector('.el-dialog__body').style.height = 'calc(100% - ' + dialogHeaderEl.offsetHeight + 'px)';
          dragDom.querySelector('.el-dialog__body').style.overflow = "auto";
          hasSetBodyHeight = true;
        }
      } else {
        let i = maxMin.querySelector('.el-icon-crop');
        i.classList.remove('el-icon-crop');
        i.classList.add('el-icon-full-screen');
        maxMin.innerHTML =
          '<i class="el-icon-full-screen" style="font-size: 16px; display: block; margin: 3px;" onMouseOver="this.style.color=\'#e94646\'" onMouseOut="this.style.color=\'#409eff\'"></i>';
        maxMin.title = '最大化';
        dragDom.style.height = "auto";
        if (dragDom.children[1] && dragDom.children[1].clientHeight === 0) {
          dragDom.style.height = nowHeight + 'px';
        }
        dragDom.style.width = nowWidth + 'px';
        dragDom.style.marginTop = nowMarginTop;
        dragDom.style.marginBottom = '50px';
        dragDom.style.borderRadius = '4px';
        dragDom.querySelector('.el-dialog__body').style.overflow = "";
        hasSetBodyHeight = false;
      }
      // 最大化最小化回调
      if (binding.value) {
        if (binding.value.fun) {
          binding.value.fun({isFullScreen: isFullScreen});
        }
      }
    }

    //未设置参数的情况=默认隐藏放大缩小,不可点击 - 或者设置可放大缩小
    maxMin.style.display = 'none';
    dialogHeaderEl.ondblclick = null;
    maxMin.onclick = null;
    if (binding.value) {
      if (!!binding.value.maxFlag) {
        maxMin.style.display = 'initial';
        maxMin.onclick = setMaxMin;
        dialogHeaderEl.ondblclick = setMaxMin;
      }
    }
    //关闭窗口后,恢复可能变高的el-dialog__body
    cls.onclick = function () {
      let a = dragDom.querySelector('.el-dialog__body').style.height = ""
    }

    // 窗口移动事件
    const moveDown = (e) => {
      // 鼠标按下,计算当前元素距离可视区的距离
      const disX = e.clientX - dialogHeaderEl.offsetLeft
      const disY = e.clientY - dialogHeaderEl.offsetTop
      // 获取到的值带px 正则匹配替换
      let styL, styT
      // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
      if (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', '')
        styT = +sty.top.replace('px', '')
      }
      document.onmousemove = function (e) {
        // 通过事件委托,计算移动的距离
        const l = e.clientX - disX
        const t = e.clientY - disY
        // 移动当前元素
        dragDom.style.left = `${l + styL}px`
        dragDom.style.top = `${t + styT}px`
        // 将此时的位置传出去
        // binding.value({x:e.pageX,y:e.pageY})
      }
      document.onmouseup = function (e) {
        const dragDom = el.querySelector('.el-dialog')
        const offsetLeft = dragDom.offsetLeft
        const offsetTop = dragDom.offsetTop
        const left = Number(dragDom.style.left.replace('px', '')) + 8
        const top = Number(dragDom.style.top.replace('px', ''))
        const windowWidth = window.innerWidth - 16
        const windowHeight = window.innerHeight
        const offsetRight = offsetLeft + dragDom.offsetWidth - windowWidth
        const offsetBottom = offsetTop + dragDom.offsetHeight - windowHeight
        // if (offsetLeft < 0) {
        //   dragDom.style.left = (left - offsetLeft) + 'px'
        // }
        if (offsetTop < 3) {
          dragDom.style.top = (top - offsetTop) + 'px'
        }
        // if (offsetRight > 0) {
        //   dragDom.style.left = (left - offsetRight) + 'px'
        // }
        let calcValue = dragDom.offsetHeight - 30
        if (offsetBottom > calcValue) {
          dragDom.style.top = (top - offsetBottom + dragDom.offsetHeight - 30) + 'px'
        }
        document.onmousemove = null
        document.onmouseup = null
      }
      //return false不加的话可能导致黏连,就是拖到一个地方时div粘在鼠标上不下来,相当于onmouseup失效
      return false
    }
    // 无传参数的情况-默认可拖拽窗口-未设置参数的情况,或者设置可拖拽的情况
    el.style.overflow = 'hidden';
    dialogHeaderEl.style.cursor = 'move'
    dialogHeaderEl.onmousedown = moveDown;
    // 设置窗口移动
    if (binding.value) {
      if (!!!binding.value.dragFlag) {
        dialogHeaderEl.style.cursor = 'initial';
        dialogHeaderEl.onmousedown = null;
        // 不可拖拽的情况,设置弹窗外部可以自动滚动,
        el.style.overflow = 'auto';
      }
    }
  }
}

如何使用?

1.在main.js文件直接注入:

import elDragDialog from '@/directive/el-drag-dialog';
Vue.directive('el-drag-dialog', elDragDialog);

2.新建vue新页面:

 <el-dialog v-el-drag-dialog>
    …other UI content…
 </el-dialog>

v-el-drag-dialog 无参情况:没有回调,可拖拽,不可最大化

          fun: callBackMaxMin, // 最大化方法回调。
          maxFlag:true,  // 是否允许窗口最大化-默认不允许
          dragFlag: false  // 是否允许拖拽-默认可拖拽
// 存在参数的写法:
v-el-drag-dialog="{ fun: callBackMaxMin, maxFlag:true,   dragFlag: false }"
目录
相关文章
|
JavaScript
VUE element-ui之el-form表单点击按钮自动增加表单(输入框),可新增删除
VUE element-ui之el-form表单点击按钮自动增加表单(输入框),可新增删除
2151 0
VUE element-ui之el-form表单点击按钮自动增加表单(输入框),可新增删除
|
JavaScript
VUE element-ui之el-popover弹出框在局部全屏下不显示问题及弹框、小箭头背景修改
VUE element-ui之el-popover弹出框在局部全屏下不显示问题及弹框、小箭头背景修改
2813 0
VUE element-ui之el-popover弹出框在局部全屏下不显示问题及弹框、小箭头背景修改
|
3月前
|
JavaScript
vue 计算属性,实现复选框的全选和反选 【小案例】
本文通过一个Vue.js小案例,展示了如何使用计算属性实现复选框的全选和反选功能。计算属性的完整写法包括get和set两部分,分别用于获取值和设置值。在全选和反选的场景中,计算属性的get方法用于判断所有复选框是否都已选中,从而控制全选复选框的状态;计算属性的set方法则用于根据全选复选框的状态,批量更新每个复选框的选中状态。通过示例代码和效果图,文章清晰地说明了计算属性在实现这一功能中的作用和效果。
vue 计算属性,实现复选框的全选和反选 【小案例】
|
5月前
|
JavaScript
vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)
vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)
235 0
|
5月前
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
Element UI 自定义/修改下拉弹窗的样式(如级联选择器的下拉弹窗样式)
510 0
|
JavaScript
element-ui的popover弹出框点击取消
element-ui的popover弹出框点击取消
277 1
|
JavaScript
Vue中使用element-ui的el-dialog对话框,实现拖拽效果(整理)
Vue中使用element-ui的el-dialog对话框,实现拖拽效果(整理)
|
小程序
button按钮组件
button按钮组件
element-ui框架的el-dialog弹出框被遮罩层遮挡问题
element-ui框架的el-dialog弹出框被遮罩层遮挡问题
572 0
|
JavaScript
Vue antdv dropdown 自定义下拉内容 overlay 禁止点击事件下传导致收起
Vue antdv dropdown 自定义下拉内容 overlay 禁止点击事件下传导致收起
361 0