Files
element-plus/packages/loading/src/createLoadingComponent.ts
bastarder ee3b42fb09 feat(loading): add loading component (#447)
* refactor(loading): refactored loading component

* refactor(loading): use render & createVNode instead of createApp

Co-authored-by: Ryan <ryanzhao2128@gmail.com>
2020-10-23 10:15:49 +08:00

118 lines
2.9 KiB
TypeScript

import { createVNode, reactive, ref, toRefs, h, Transition, render, VNode } from 'vue'
import { removeClass } from '@element-plus/utils/dom'
import type { ILoadingCreateComponentParams, ILoadingInstance } from './loading'
export function createLoadingComponent({ options , globalLoadingOption }: ILoadingCreateComponentParams): ILoadingInstance {
let vm: VNode = null
let afterLeaveTimer: Nullable<number> = null
const afterLeaveFlag = ref(false)
const data = reactive({
...options,
originalPosition: '',
originalOverflow: '',
visible: options.hasOwnProperty('visible') ? options.visible : true,
})
function setText(text: string) {
data.text = text
}
function destorySelf() {
const target = data.parent
if(!target.vLoadingAddClassList) {
removeClass(target, 'el-loading-parent--relative')
removeClass(target, 'el-loading-parent--hidden')
}
if (vm.el && vm.el.parentNode) {
vm.el.parentNode.removeChild(vm.el)
}
}
function close() {
const target = data.parent
target.vLoadingAddClassList = null
if (data.fullscreen) {
globalLoadingOption.fullscreenLoading = undefined
}
afterLeaveFlag.value = true
clearTimeout(afterLeaveTimer)
afterLeaveTimer = window.setTimeout(() => {
if (afterLeaveFlag.value) {
afterLeaveFlag.value = false
destorySelf()
}
}, 400)
data.visible = false
}
function handleAfterLeave() {
if (!afterLeaveFlag.value) return
afterLeaveFlag.value = false
destorySelf()
}
const componetSetupConfig = {
...toRefs(data),
setText,
close,
handleAfterLeave,
}
const elLoadingComponent = {
name: 'ElLoading',
setup() {
return componetSetupConfig
},
render() {
const spinner = h('svg', {
class: 'circular',
viewBox: '25 25 50 50',
}, [
h('circle', { class: 'path', cx: '50', cy: '50', r: '20', fill: 'none' }),
])
const noSpinner = h('i', { class: this.spinner })
const spinnerText = h('p', { class: 'el-loading-text' }, [this.text])
return h(Transition, {
name: 'el-loading-fade',
onAfterLeave: this.handleAfterLeave,
},{
default: () => h('div', {
style: {
backgroundColor: this.background || '',
display: this.visible ? 'inherit' : 'none',
},
class: [
'el-loading-mask',
this.customClass,
this.fullscreen ? 'is-fullscreen' : '',
],
}, [
h('div', {
class: 'el-loading-spinner',
}, [
!this.spinner ? spinner : noSpinner,
this.text ? spinnerText : null,
]),
]),
})
},
}
vm = createVNode(elLoadingComponent)
render(vm, document.createElement('div'))
return {
...componetSetupConfig,
vm,
get $el(){
return vm.el as HTMLElement
},
}
}