@prettyy/ui
Version:
vue2 UI
137 lines (118 loc) • 4.62 kB
JavaScript
import loadingVue from "../loading/src/main.vue"
import afterLeave from "../../utils/after-leave"
import { getStyle, removeClass, addClass } from "../../utils/dom"
import { t } from '../../locale'
import vue from 'vue'
const VLoading = vue.extend(loadingVue)
const loadingDirective = {}
loadingDirective.install = Vue => {
const insertDom = (parent, el, binding) => {
if (!el.domVisible && getStyle(el, 'display') !== 'none' && getStyle(el, 'visibility') !== 'hidden') {
Object.keys(el.maskStyle).forEach(property => {
el.mask.style[property] = el.maskStyle[property]
})
if (el.originalPosition !== 'absolute' && el.originalPosition !== 'fixed' && el.originalPosition !== 'sticky') {
addClass(parent, 'vl-loading-parent--relative')
}
if (binding.modifiers.lock) {
addClass(parent, 'vl-loading-parent--hidden')
}
el.domVisible = true
parent.appendChild(el.mask)
Vue.nextTick(() => {
if (el.instance.hiding) {
el.instance.$emit('after-leave')
} else {
el.instance.visible = true
}
})
el.domInserted = true
} else if (el.domVisible && el.instance.hiding === true) {
el.instance.visible = true
el.instance.hiding = false
}
}
const toggleLoading = (el, binding) => {
if (binding.value) {
vue.nextTick(() => {
if (binding.modifiers.fullscreen) {
el.originalPosition = getStyle(document.body, 'position')
el.originalOverflow = getStyle(document.body, 'overflow')
addClass(el.mask, 'is-fullscreen')
insertDom(document.body, el, binding)
} else {
removeClass(el.mask, 'is-fullscreen')
// 设置了基于body
if (binding.modifiers.body) {
el.originalPosition = getStyle(document.body, 'position');
['top', 'left'].forEach(property => {
const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft'
el.maskStyle[property] = el.getBoundingClientRect()[property] +
document.body[scroll] +
document.documentElement[scroll] -
parseInt(getStyle(document.body, `margin-${property}`), 10) +
'px'
});
['height', 'width'].forEach(property => {
el.maskStyle[property] = document.body.getBoundingClientRect()[property] + 'px'
})
insertDom(document.body, el, binding)
} else {
el.originalPosition = getStyle(el, 'position')
insertDom(el, el, binding)
}
}
})
} else {
// eslint-disable-next-line no-unused-vars
afterLeave(el.instance, _ => {
if (!el.instance.hiding) return
el.domVisible = false
const target = binding.modifiers.body ? document.body : el
removeClass(target, 'vl-loading-parent--relative')
removeClass(target, 'vl-loading-parent--hidden')
el.instance.hiding = false
}, 300, true)
el.instance.visible = false
el.instance.hiding = true
}
}
Vue.directive('loading', {
bind: function (el, binding, vnode) {
const textExr = el.getAttribute('loading-text') || t('vl.loading.text')
const backgroundExr = el.getAttribute('loading-background') || ''
const customClassExr = el.getAttribute('loading-custom-class')
const vm = vnode.context
const mask = new VLoading({
el: document.createElement('div'),
data: {
text: vm && vm[textExr] || textExr,
background: vm && vm[backgroundExr] || backgroundExr,
customClass: vm && vm[customClassExr] || customClassExr,
fullscreen: !!binding.modifiers.fullscreen
}
})
el.instance = mask
el.mask = mask.$el
el.maskStyle = {}
binding.value && toggleLoading(el, binding)
},
inserted: function (){},
update: function (el, binding) {
el.instance.setText(el.getAttribute('loading-text'))
if (binding.oldValue !== binding.value) {
toggleLoading(el, binding)
}
},
unbind: function (el, binding) {
if (el.domInserted) {
el.mask &&
el.mask.parentNode &&
el.mask.parentNode.removeChild(el.mask)
toggleLoading(el, { value: false, modifiers: binding.modifiers })
}
el.instance && el.instance.$destroy()
}
})
}
export default loadingDirective