最近,工作上需要,在el-dialog基础上封装了一个可最大化,还原,拖动,调整dialog大小的功能,本来妹子只想简单的用用别人分享出来的代码的,无奈有很多BUG,比如没做移动范围限制,导致能移动到可视窗口外导致无法关闭;调整大小时会出现宽度,高度超过可视区域而引起样式问题,以及滚动条会让可拖动区域失效等问题;然后跟我本来的最大化跟还原功能有部分冲突,导致dialog有很多其他问题。所以妹子只好自己写了(泪目),该代码还是参考了网上别人的部分代码,具体是参考的哪个不记得了(原谅妹子记性不好。。。),如果是用的哪位兄弟的,可以私信我,谢谢。
大概思路就是,单独封装了一个max-dialog的组件,增加了自定义指令v-dialogDrag,然后注册指令,具体注册指令的代码,可以去看官网。
本人项目下其他页面的代码如下:
components/max-dialog/index.vue
<!--
@author: debbie.wong;
@email:[email protected]
-->
<template>
<el-dialog ref="maxDialog" custom-class="dialogHeightFull maxDialog" :title="title" :fullscreen="fullFlag"
:visible.sync="maxdialogVisible" :append-to-body="true" :close-on-click-modal="false" :show-close="false"
:width="width" :top="top" v-if="maxdialogVisible" @closed="closeMaxDialog" v-dialogDrag>
<div slot="title" class="maxDialog-header">
<div class="maxDialog-title"><span>{{title}}</span></div>
<div class="maxDialog-icon">
<i :class="fullFlag? 'el-icon-copy-document' : 'el-icon-full-screen' " @click="IsFullscreen"></i>
<i class="el-icon-close" @click="closeMaxDialog"></i>
</div>
</div>
<slot name="content" :style="{height:height}"></slot>
<div class="resize"></div>
</el-dialog>
</template>
<script>
export default {
name: 'maxDialog',
props: {
dialogVisible: {
type: Boolean,
default: false
},
titleVisible: {
type: Boolean,
default: true
},
width: {
type: String,
default: '1200px'
},
height: {
type: String,
default: '100%'
},
top: {
type: String,
default: '30px'
},
title: {
type: String,
default: ''
},
isfullscreen: {
type: Boolean,
default: false // 默认全屏
}
},
data() {
return {
full: false, // 全屏
}
},
computed: {
fullFlag: {
get: function() {
return this.full ?? this.isfullscreen;
},
set: function(n) {
return this.full
}
},
maxdialogVisible:{ //重新设置一个变量,接收父级传递的参数
get:function(){
return this.dialogVisible
},
set :function(value){
this.$emit('update:dialogVisible', false)
}
}
},
mounted() {
},
methods: {
// 全屏 切换
IsFullscreen() {
let dialogDom = document.querySelector(".maxDialog");
if (this.isfullscreen == true) {
this.full = this.full === null ? false : !this.full
} else {
this.full = this.full === null ? true : !this.full
dialogDom.style.top =`0px`;
dialogDom.style.left =`auto`;
}
// 传过来的全屏钩子函数
this.$emit('maxFun')
},
// 关闭
closeMaxDialog() {
this.full = null
this.$emit('update:dialogVisible', false)
// 传过来的关闭钩子函数
this.$emit('closeFun')
}
},
created() {
this.full = this.isfullscreen
},
}
</script>
<style scoped="scoped">
>>>.el-dialog__header {
background-color: #f2f2f2;
/* height: 48px; */
padding: 10px 20px 10px;
}
.maxDialog-header {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.maxDialog .maxDialog-icon i {
display: inline-block;
height: 28px;
width: 28px;
line-height: 24px;
text-align: center;
border-radius: 50%;
cursor: pointer;
font-size: 22px;
}
.maxDialog .maxDialog-icon i:hover {
background-color: #ddd;
}
.maxDialog .maxDialog-icon i::before {
font-size: 80%;
}
>>>.maxDialog.dialogHeightFull.el-dialog {
margin-bottom: 0;
overflow-y: hidden;
}
.el-dialog__wrapper{
overflow: hidden!important;
}
.resize{
position: absolute;
right: 0;
bottom: 0;
content: '';
width: 10px;
height: 10px;
cursor: se-resize;
}
</style>
src/directive/dialog.js
/**
@author: debbie.wong;
@email:[email protected]
*/
import Vue from 'vue'
Vue.directive("dialogDrag", {
bind(el, binding, vnode, oldVnode) {
const windowW = document.body.clientWidth;
const windowH = document.body.clientHeight
//设置弹框可拉伸最小宽高
let minWidth = 400;
let minHeight = 300;
const dialogHeaderEl = el.querySelector(".el-dialog__header");
//弹窗
const dragDom = el.querySelector(".el-dialog");
//头部加上可拖动cursor
dialogHeaderEl.style.cursor = "move";
// 获取style属性
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null);
let moveDown = e => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
// 获取到的值带px 正则匹配替换
let styL, styT, styMT;
// 注意在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/g, "");
styT = +sty.top.replace(/\px/g, "");
styMT = +sty.marginTop.replace(/\px/g, "")
}
document.onmousemove = function (e) {
const titleH = dialogHeaderEl.offsetHeight;
// 通过事件委托,计算移动的距离
let l = e.clientX - disX;
let t = e.clientY - disY;
// 移动边界处理
if (t < 0 && (t + styMT + styT) <= 0 || t < 0 && (styMT + styT) <= 0) {
t = -(styMT + styT);
} else if (t > 0 && t > (document.body.clientHeight - styMT - styT - titleH)) {
t = document.body.clientHeight - styMT - styT - titleH;
}
// 移动当前元素
dragDom.style.left = `${l + styL}px`;
dragDom.style.top = `${t + styT}px`;
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
};
dialogHeaderEl.onmousedown = moveDown;
dragDom.onmousemove = function (e) {
const dialogBODY = el.querySelector(".el-dialog__body");
const resizeDom= el.querySelector(".resize");
const titleH = dialogHeaderEl.offsetHeight;
dragDom.onmousedown = e => {
const clientX = e.clientX;
const clientY = e.clientY;
let elW = dragDom.clientWidth;
let elH = dragDom.clientHeight;
let EloffsetLeft = dragDom.offsetLeft;
let EloffsetTop = dragDom.offsetTop;
dragDom.style.userSelect = "none";
let ELscrollTop = el.scrollTop;
let resizeW = resizeDom.clientWidth, resizeH = resizeDom.clientHeight;
//判断点击的位置是不是为头部
if (
clientX > EloffsetLeft &&
clientX < EloffsetLeft + elW &&
clientY > EloffsetTop &&
clientY < EloffsetTop + 100
) {
//如果是头部
} else {
document.onmousemove = function (e) {
e.preventDefault(); // 移动时禁用默认事件
//鼠标拖拽
if (
clientX > EloffsetLeft + elW - resizeW &&
clientX < EloffsetLeft + elW
) {
//往左拖拽
if (clientX > e.clientX) {
if (dragDom.clientWidth < minWidth) {
} else {
dragDom.style.width = elW - (clientX - e.clientX) * 2 + "px";
}
}
//往右拖拽
if (clientX <= e.clientX) {
let targetTW = elW + (e.clientX - clientX) * 2
targetTW > windowW ?
dragDom.style.width = windowW + "px" :
dragDom.style.width = targetTW + "px"
}
}
//底部鼠标拖拽位置
if (
ELscrollTop + clientY > EloffsetTop + elH - resizeH &&
ELscrollTop + clientY < EloffsetTop + elH
) {
//往上拖拽
if (clientY > e.clientY) {
if (dragDom.clientHeight < minHeight) {
} else {
dragDom.style.height = elH - (clientY - e.clientY) * 1 + "px";
dialogBODY.style.height = elH - (clientY - e.clientY) * 1 - titleH + "px";
}
}
//往下拖拽
if (clientY <= e.clientY) {
e.clientY >= windowH ?
dragDom.style.height = windowH - dragDom.offsetTop + "px" :
dragDom.style.height = elH + (e.clientY - clientY) * 1 + "px";
dialogBODY.style.height = elH - (clientY - e.clientY) * 1 - titleH + "px";
}
}
};
//结束
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
};
};
}
});
export default Vue.directive('dialogDrag')
希望对某些小伙伴有帮助,有问题可以评论,谢谢。