改组件继承el-dialog组件百分之95属性,可直接对<el-dialog>进行替换。在项目中我的命名为:
SkDialog。废话不多说,直接上代码:
vue代码:搞成组件,路径随意,推荐统一放在组件目录下
<!--
@author: kzy;
-->
<template>
<el-dialog ref="skDialog"
custom-class="dialogHeightFull skDialog"
:title="title"
:fullscreen="fullFlag"
:visible.sync="dialogVisible"
:append-to-body="appendToBody"
:lock-scroll="lockScroll"
:modal-append-to-body="modalAppendToBody"
:close-on-click-modal="closeOnClickModal"
:close-on-press-escape="closeOnPressEscape"
:show-close="false"
:before-close="beforeClose"
:center="center"
:destroy-on-close="destroyOnClose"
:width="width"
:top="top"
v-if="dialogVisible"
v-sk-dialog-drag
@closed="closeSkDialog">
<div slot="title" class="skDialog-header">
<div class="skDialog-title"><span>{{title}}</span></div>
<div class="skDialog-icon">
<i :class="fullFlag? 'el-icon-copy-document' : 'el-icon-full-screen' " @click="IsFullscreen"></i>
<i class="el-icon-close" @click="closeSkDialog"></i>
</div>
</div>
<div class="el-dialog__body" v-if="rendered"><slot :style="{height:height}"></slot></div>
<div class="el-dialog__footer" v-if="$slots.footer">
<slot name="footer"></slot>
</div>
<div class="resize"></div>
</el-dialog>
</template>
<script>
export default {
name: 'SkDialog',
props: {
visible: {
type: Boolean,
default: false
},
titleVisible: {
type: Boolean,
default: true
},
width: {
type: String,
default: '50%'
},
height: {
type: String,
default: '100%'
},
top: {
type: String,
default: '30px'
},
title: {
type: String,
default: ''
},
isfullscreen: {
type: Boolean,
default: false // 默认全屏
},
modal: {
type: Boolean,
default: true
},
modalAppendToBody: {
type: Boolean,
default: true
},
appendToBody: {
type: Boolean,
default: true
},
lockScroll: {
type: Boolean,
default: true
},
closeOnClickModal: {
type: Boolean,
default: false
},
closeOnPressEscape: {
type: Boolean,
default: false
},
showClose: {
type: Boolean,
default: true
},
customClass: {
type: String,
default: ''
},
beforeClose: Function,
center: {
type: Boolean,
default: false
},
destroyOnClose: Boolean
},
data() {
return {
full: false, // 全屏
}
},
computed: {
fullFlag: {
get: function() {
return this.full ?? this.isfullscreen;
},
set: function(n) {
return this.full
}
},
dialogVisible:{ //重新设置一个变量,接收父级传递的参数,引用页面需要使用语法糖,才能使用this.$emit('update:visible', false)对父组件值进行更新
get:function(){
return this.visible
},
set :function(value){
this.$emit('update:visible', false)
}
},
rendered:{ //重新设置一个变量,接收父级传递的参数
get:function(){
return this.visible
},
}
},
mounted() {
},
methods: {
// 全屏 切换
IsFullscreen() {
let dialogDom = document.querySelector(".skDialog");
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')
},
// 关闭
closeSkDialog() {
this.full = null
this.$emit('update:visible', false)
// 传过来的关闭钩子函数
this.$emit('closeFun')
}
},
watch:{
},
created() {
this.full = this.isfullscreen
},
}
</script>
<style scoped="scoped">
>>>.el-dialog__header {
background-color: #f2f2f2;
/* height: 48px; */
padding: 10px 20px 10px;
}
.skDialog-header {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.skDialog .skDialog-icon i {
display: inline-block;
height: 28px;
width: 28px;
line-height: 24px;
text-align: center;
border-radius: 50%;
cursor: pointer;
font-size: 22px;
}
.skDialog .skDialog-icon i:hover {
background-color: #ddd;
}
.skDialog .skDialog-icon i::before {
font-size: 80%;
}
>>>.skDialog.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>
拖动及缩放操作js代码:
/**
@author: kzy;
*/
import Vue from 'vue'
Vue.directive("SkDialogDrag", {
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;
let ELscrollTop = el.scrollTop;
let resizeW = resizeDom.clientWidth, resizeH = resizeDom.clientHeight;
//判断点击的位置是不是为头部
if (
clientX > EloffsetLeft &&
clientX < EloffsetLeft + elW &&
clientY > EloffsetTop &&
clientY < EloffsetTop + 100
) {
//如果是头部
e.preventDefault(); // 移动时禁用默认事件
} else {
document.onmousemove = function (e) {
//鼠标拖拽
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('SkDialogDrag')
将skdialog.js注册为指令:
目录:
import SkDialogDrag from './dialog/skdialog'
const install = function(Vue) {
Vue.directive('SkDialogDrag', SkDialogDrag)
}
指令使用:(v-指令名称(SkDialogDrag))
效果图:
注:吃水不忘挖井人,在 原作者wjqocean 的基础之上改进