自定义弹窗拖拽指令
第一步: src目录下新建目录directive,然后在directive目录下的新建文件el-drag-dialog.js,在该文件里实现了拖拽逻辑。
el-drag-dialog.js文件代码如下:
export default {
bind(el, binding, vnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null)
const getStyle = (function() {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr]
}
})()
dialogHeaderEl.onmousedown = e => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomHeight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
const minDragDomLeft = dragDom.offsetLeft
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
const minDragDomTop = dragDom.offsetTop
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
// 获取到的值带px 正则匹配替换
let styL = getStyle(dragDom, 'left')
let styT = getStyle(dragDom, 'top')
if (styL.includes('%')) {
// eslint-disable-next-line no-useless-escape
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
// eslint-disable-next-line no-useless-escape
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
} else {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
let 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
}
if (top < -disY) { top = 0 }
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
// emit onDrag event
vnode.child.$emit('drag-dialog')
}
document.onmouseup = function() {
document.onmousemove = null
document.onmouseup = null
}
}
}
}
第二步:全局注册指令。
directive目录下新建文件 index.js,在该文件中使用Vue.directive注册指令。
index.js:
import Vue from 'vue'
import elDragDialog from './el-drag-dialog'
Vue.directive('el-drag-dialog', elDragDialog) // v-el-drag-dialog 弹框拖拽指令
第三步:在 main.js 引入
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store/index'
import './directive/index.js' // 全局指令注册
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
第四步:使用v-el-drag-dialog 弹框拖拽指令。
<template>
<el-dialog
v-el-drag-dialog
:visible.sync="dialogVisible"
title="查看详情"
:close-on-click-modal="false"
width="80%"
top="10vh"
@close="$emit('update:visible',false)"
>
<div>请按住标题栏部分进行拖拽,移动弹窗</div>
</el-dialog>
</template>
<script>
export default {
props: {
visible: {
type: Boolean,
default: false
},
},
data() {
return {
}
},
computed: {
dialogVisible: {
get() {
return this.visible
},
set(newVal) {
console.log(newVal)
}
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog {
height: 82%;
.el-dialog__body {
max-height: 94%;
}
}
::v-deep .el-dialog__title {
margin-left: 36px;
}
</style>