zoro-cli
Version:
https://github.com/vuejs/vue-cli
113 lines (105 loc) • 2.7 kB
JavaScript
import {
once,
on,
off,
disableBodyScroll,
enableBodyScroll,
disableTouchPropagation,
enableTouchPropagation,
} from 'src/util'
const { body } = document
let modals = []
export function cleanModals() {
modals.forEach(modal => {
if (modal.$destroy && !modal._mixinModalIsStale) {
modal.$destroy()
}
})
modals = []
}
/**
* - 引入依赖: `import ModalMixin from 'src/component/ModalMixin'`
* - 继承 mixin: `mixins: [ModalMixin]`
* - mask样式: `modalMaskClass: ''`
* - 透明遮罩: `transparentMask: true`
* - 禁用遮罩: `noMask: true`
* - 劫持 back: `hijackBack: true`, 需要同时定义 onBack 来处理 back
* - 比如 this.$emit('cancel')
* - 比如 this.$destroy()
* - onBack: `onBack: Function`
* - handleClickMask: `handleClickMask: Function`
* - 定义 css: width/height/font-size
*/
export default {
created() {
if (!this.$parent) {
this.$mount()
this._mixinAppendToBody()
modals.push(this)
}
},
destroyed() {
const { $el, noMask } = this
if ($el) {
enableTouchPropagation($el)
if (!noMask) {
// 有遮罩
const mask = $el.parentNode
if (mask) {
if (this._mixinHandleClickMask) {
off(mask, 'click', this._mixinHandleClickMask)
}
enableBodyScroll()
body.removeChild(mask)
}
} else {
// 无遮罩
body.removeChild($el)
}
this._mixinModalIsStale = true
}
},
methods: {
// 添加到 body 上
_mixinAppendToBody() {
disableTouchPropagation(this.$el)
if (!this.noMask) {
this._mixinAppendWithMask()
this._mixinHijackBack()
} else {
body.appendChild(this.$el)
}
},
// 有遮罩
_mixinAppendWithMask() {
const mask = document.createElement('div')
mask.classList.add('modal-mask')
if (this.transparentMask) {
mask.classList.add('transparent')
}
if (this.modalMaskClass) {
mask.classList.add(this.modalMaskClass)
}
if (typeof this.handleClickMask === 'function') {
this._mixinHandleClickMask = (event = {}) => {
if (event.target === mask) {
this.handleClickMask(event)
}
}
on(mask, 'click', this._mixinHandleClickMask)
}
disableBodyScroll()
mask.appendChild(this.$el)
body.appendChild(mask)
},
// 劫持 back 事件, 并销毁
_mixinHijackBack() {
if (this.hijackBack && typeof this.onBack === 'function') {
once(document, 'back', e => {
e.preventDefault()
this.onBack()
})
}
},
},
}