1.主文件
import Vue from 'vue'
import mixins from './mixins'
import store from '@/store'
import router from '@/router'
function getModalInstance(component) {
if (!component.methods) {
component.methods = {}
}
component.methods.destroy = mixins.methods.destroy
component.directives = mixins.directives
const ModalInstanceConstructor = Vue.extend(component)
return new ModalInstanceConstructor()
}
export const modalObj = {
show(cmp, payload, callback) {
return new Promise((resolve, reject) => {
if (cmp) {
const Instance = getModalInstance(cmp.default)
Instance.payload = payload
Instance.resolve = resolve
Instance.callback = callback
// 注入store,router
Instance.$$store = Instance.$store = store
Instance.$$router = router
const component = Instance.$mount()
document.body.appendChild(component.$el)
const modal = Instance.$children[0]
modal.hide = () => {
Instance.visible = false
Instance.destroy()
}
Instance.visible = true
// modal.$emit('update:visible', false)
} else {
reject(new Error('modal组件未找到'))
}
})
}
}
export default {
install: vue => {
vue.prototype.$modal = modalObj
}
}
2.混合引入
export default {
methods: {
data() {
return {
visible: false,
isDestroy: false
}
},
destroy() {
if (!this.isDestroy) {
this.visible = false
this.isDestroy = true
setTimeout(() => {
this.$destroy()
document.body.removeChild(this.$el)
}, 300)
}
}
},
directives: {
drag: {
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 = (() => {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
}
return (dom, attr) => getComputedStyle(dom, false)[attr]
})()
dialogHeaderEl.onmousedown = eD => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = eD.clientX - dialogHeaderEl.offsetLeft
const disY = eD.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 = eM => {
// 通过事件委托,计算移动的距离
let left = eM.clientX - disX
let top = eM.clientY - disY
// 边界处理
if (-left > minDragDomLeft) {
left = -minDragDomLeft
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft
}
if (-top > minDragDomTop) {
top = -minDragDomTop
} else if (top > maxDragDomTop) {
top = maxDragDomTop
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
// emit onDrag event
vnode.child.$emit('dragDialog')
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
}
}
}
}
}
}
3.使用
# 弹框插件使用
调用弹框
```js
// 一、调用弹框
this.$modal.show(require('./modals/openModel'), { openData: row.id }).then((data)=>{})
// 二、弹框获取参数
this.payload.openData
// 三、执行回调
//多类型回调
this.resolve('setting')
//单个回调
this.resolve()
//销毁弹框
this.destroy()
```
4.main.js-------------引入
import modal from '@/utils/Modal'
Element.Dialog.props.closeOnClickModal.default = false
Vue.use(Element, { size: 'mini', zIndex: 3000 })
Vue.use(modal)