fix(loading): fix loading transition invalid (#1321)

This commit is contained in:
Ryan2128 2021-01-20 01:26:14 -06:00 committed by GitHub
parent 5e031237e3
commit 45dbdf6e26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 14 deletions

View File

@ -268,6 +268,8 @@ describe('Loading', () => {
</template>
</el-input>`,
})
await nextTick()
await nextTick()
const maskDisplay = getComputedStyle(wrapper.find('.el-loading-mask').element).display
expect(maskDisplay).toBe('block')
})

View File

@ -2,7 +2,10 @@ import { createVNode, h, reactive, ref, render, toRefs, Transition, VNode, vShow
import { removeClass } from '@element-plus/utils/dom'
import type { ILoadingCreateComponentParams, ILoadingInstance } from './loading.type'
export function createLoadingComponent({ options , globalLoadingOption }: ILoadingCreateComponentParams): ILoadingInstance {
export function createLoadingComponent({
options,
globalLoadingOption,
}: ILoadingCreateComponentParams): ILoadingInstance {
let vm: VNode = null
let afterLeaveTimer: Nullable<number> = null
@ -11,7 +14,7 @@ export function createLoadingComponent({ options , globalLoadingOption }: ILoadi
...options,
originalPosition: '',
originalOverflow: '',
visible: options.hasOwnProperty('visible') ? options.visible : true,
visible: false,
})
function setText(text: string) {
@ -20,8 +23,15 @@ export function createLoadingComponent({ options , globalLoadingOption }: ILoadi
function destroySelf() {
const target = data.parent
if(!target.vLoadingAddClassList) {
removeClass(target, 'el-loading-parent--relative')
if (!target.vLoadingAddClassList) {
let loadingNumber: number | string = target.getAttribute('loading-number')
loadingNumber = Number.parseInt(loadingNumber) - 1
if (!loadingNumber) {
removeClass(target, 'el-loading-parent--relative')
target.removeAttribute('loading-number')
} else {
target.setAttribute('loading-number', loadingNumber.toString())
}
removeClass(target, 'el-loading-parent--hidden')
}
if (vm.el && vm.el.parentNode) {
@ -53,7 +63,7 @@ export function createLoadingComponent({ options , globalLoadingOption }: ILoadi
destroySelf()
}
const componetSetupConfig = {
const componentSetupConfig = {
...toRefs(data),
setText,
close,
@ -63,7 +73,7 @@ export function createLoadingComponent({ options , globalLoadingOption }: ILoadi
const elLoadingComponent = {
name: 'ElLoading',
setup() {
return componetSetupConfig
return componentSetupConfig
},
render() {
const spinner = h('svg', {
@ -108,9 +118,9 @@ export function createLoadingComponent({ options , globalLoadingOption }: ILoadi
render(vm, document.createElement('div'))
return {
...componetSetupConfig,
...componentSetupConfig,
vm,
get $el(){
get $el() {
return vm.el as HTMLElement
},
}

View File

@ -14,7 +14,7 @@ const createInstance = (el, binding) => {
fullscreen: !!binding.modifiers.fullscreen,
target: !!binding.modifiers.fullscreen ? null : el,
body: !!binding.modifiers.body,
visible: !!binding.value,
visible: true,
lock: !!binding.modifiers.lock,
})
}

View File

@ -1,5 +1,6 @@
import { nextTick } from 'vue'
import { createLoadingComponent } from './createLoadingComponent'
import type { ILoadingOptions, ILoadingInstance, ILoadingGlobalConfig } from './loading.type'
import type { ILoadingGlobalConfig, ILoadingInstance, ILoadingOptions } from './loading.type'
import { addClass, getStyle, removeClass } from '@element-plus/utils/dom'
import PopupManager from '@element-plus/utils/popup-manager'
import isServer from '@element-plus/utils/isServer'
@ -19,14 +20,20 @@ const globalLoadingOption: ILoadingGlobalConfig = {
fullscreenLoading: null,
}
const addStyle = (options: ILoadingOptions, parent: HTMLElement, instance: ILoadingInstance) => {
const addStyle = async (options: ILoadingOptions, parent: HTMLElement, instance: ILoadingInstance) => {
const maskStyle: Partial<CSSStyleDeclaration> = {}
if (options.fullscreen) {
instance.originalPosition.value = getStyle(document.body, 'position')
instance.originalOverflow.value = getStyle(document.body, 'overflow')
maskStyle.zIndex = String(PopupManager.nextZIndex())
} else if (options.body) {
instance.originalPosition.value = getStyle(document.body, 'position');
instance.originalPosition.value = getStyle(document.body, 'position')
/**
* await dom render when visible is true in init,
* because some component's height maybe 0.
* e.g. el-table.
*/
await nextTick();
['top', 'left'].forEach(property => {
const scroll = property === 'top' ? 'scrollTop' : 'scrollLeft'
maskStyle[property] = (options.target as HTMLElement).getBoundingClientRect()[property] +
@ -59,8 +66,8 @@ const addClassList = (options: ILoadingOptions, parent: HTMLElement, instance: I
}
}
const Loading = function(options: ILoadingOptions = {}): ILoadingInstance{
if(isServer) return
const Loading = function (options: ILoadingOptions = {}): ILoadingInstance {
if (isServer) return
options = {
...defaults,
...options,
@ -95,7 +102,29 @@ const Loading = function(options: ILoadingOptions = {}): ILoadingInstance{
addClassList(options, parent, instance)
}
/**
* add loading-number to parent.
* because if a fullscreen loading is triggered when somewhere
* a v-loading.body was triggered before and it's parent is
* document.body which with a margin , the fullscreen loading's
* destroySelf function will remove 'el-loading-parent--relative',
* and then the position of v-loading.body will be error.
*/
let loadingNumber: number | string = parent.getAttribute('loading-number')
if (!loadingNumber) {
loadingNumber = 1
} else {
loadingNumber = Number.parseInt(loadingNumber) + 1
}
parent.setAttribute('loading-number', loadingNumber.toString())
parent.appendChild(instance.$el)
// after instance render, then modify visible to trigger transition
nextTick().then(() => {
instance.visible.value = options.hasOwnProperty('visible') ? options.visible : true
})
if (options.fullscreen) {
globalLoadingOption.fullscreenLoading = instance
}