elementUI中的el-dialog弹窗,是常见的高使用率的一个组件,但却不支持拖动拖拽,查了一下资料,没查到满意的实现代码,还是自己写比较稳妥,于是就有了下面的v-dialogdrag自定义指令了,因为el-dialog自身的特定实现方式,所以此指令仅限使用在el-dialog上;
此指令还支持不超出可视窗口范围的参数v-dialogdrag.in,上代码:
template:
<el-dialog
title="拖拽"
:visible.sync="showDialog"
width="30%"
v-dialogdrag.in="showDialog"
></el-dialog>
javaScript:
export default {
data(){
return {
showDialog: false
}
},
directives:{
dialogdrag:{
bind(el, binding, vnode){
let flag = true,
dialogOffsetLeft = 0,
dialogOffsetTop = 0,
dialogOffsetWidth = 0,
dialogOffsetHeight =0,
clientWidth = 0,
clientHeight = 0
let dragDialog = (el, binding)=>{
let dialog = el.querySelector('.el-dialog')
let dialogHeader = el.querySelector('.el-dialog__header')
dialogHeader.style.cursor = "move"
dialogHeader.style.userSelect = "none"//防止选中内容
dialog.style.userSelect = "none"
dialogHeader.onmousedown(eDown)=>{
dialog.style.left = (dialog.style.left && dialog.style.left!='auto')?dialog.style.left : 0
dialog.style.top = (dialog.style.top && dialog.style.top!='auto')?dialog.style.top : 0
let beginLeft = parseInt(dialog.style.left), beginTop = parseInt(dialog.style.top)
dialogOffsetWidth = dialog.offsetWidth
dialogOffsetHeight = dialog.offsetHeight
if(flag){
dialogOffsetLeft = dialog.offsetLeft
dialogOffsetTop = dialog.offsetTop
flag = false
}
document.onmousemove = (eMove)=>{
clientWidth = el.clientWidth
clientHeight = el.clientHeight
let timer = setTimeout(()=>{//节流
if(binding.modifiers && binding.modifiers.in){
//不超出可视窗口的情况
let left = beginLeft + eMove.clientX - eDown.clientX
let top = beginTop + eMove.clientY - eDown.clientY
if(left >= -dialogOffsetLeft && (left + dialogOffsetWidth + dialogOffsetLeft) <= clientWidth){
dialog.style.left = left + 'px'
}else{
//左右边界
dialog.style.left = (left < 0?-dialogOffsetLeft : (clientWidth - dialogOffsetWidth - dialogOffsetLeft)) + 'px'
}
if(top >= -dialogOffsetTop && (top + dialogOffsetHeight + dialogOffsetTop) <= clientHeight){
dialog.style.top = top + 'px'
}else{
//上下边界
dialog.style.top = (top < 0?-dialogOffsetTop : (clientHeight - dialogOffsetHeight - dialogOffsetTop)) + 'px'
}
}else{
dialog.style.left = (beginLeft + eMove.clientX - eDown.clientX) + 'px'
dialog.style.top = (beginTop + eMove.clientY - eDown.clientY) + 'px'
}
if(timer){
clearTimeOut(timer)
timer = null
}
},5)
}
document.onmouseup = (eUp)=>{
document.onmousemove = null
document.onmouseup = null
}
}
//窗口宽高变化也不超出可视窗口范围
window.addEventListener('resize', (e)=>{
dialogOffsetLeft = dialog.offsetLeft - parseInt((dialog.style.left && dialog.style.left!='auto')?dialog.style.left : 0)
dialogOffsetTop = dialog.offsetTop - parseInt((dialog.style.top && dialog.style.top!='auto')?dialog.style.top : 0)
//上下左右边界最大最小值
if(dialog.offsetLeft < 0){
dialog.style.left = -dialogOffsetLeft + 'px'
}
if(dialog.offsetRight < 0){
dialog.style.left = (el.clientWidth - dialogOffsetWidth - dialogOffsetLeft) + 'px'
}
if(dialog.offsetTop < 0){
dialog.style.top = -dialogOffsetTop + 'px'
}
if(dialog.offsetBottom < 0){
dialog.style.top = (el.clientHeight - dialogOffsetHeight - dialogOffsetTop) + 'px'
}
},false)
}
dragDialog(el, binding)
vnode.context.dragDialog = dragDialog
},
componentUpdated(el, binding, vnode){
if(typeof binding.value == 'boolean' && binding.value !== binding.oldValue){
if(binding.value){
vnode.context.dragDialog(el, binding)
}
}
if(binding.value === undefined){
vnode.context.dragDialog(el, binding)
}
}
}
}
}
参数说明:
在
v-dialogdrag.in="showDialog"
中:.in :非必填 | 是否只在可视窗口内拖拽
showDialog :Boolean | 非必填 | 窗口显示时才绑定拖拽功能(可传可不传,传了会减少点资源消耗)