mirror of https://github.com/ElemeFE/element
Loading: full screen loading is now singleton
parent
4b9a0125c2
commit
707a0d5a60
|
@ -200,6 +200,14 @@ The parameter `options` is the configuration of Loading, and its details can be
|
|||
let loadingInstance = Loading.service(options);
|
||||
loadingInstance.close();
|
||||
```
|
||||
Note that in this case the full screen Loading is singleton. If a new full screen Loading is invoked before an existing one is closed, the existing full screen Loading instance will be returned instead of actually creating another Loading instance:
|
||||
```javascript
|
||||
let loadingInstance1 = Loading.service({ fullscreen: true });
|
||||
let loadingInstance2 = Loading.service({ fullscreen: true });
|
||||
console.log(loadingInstance1 === loadingInstance2); // true
|
||||
```
|
||||
Calling the `close` method on any one of them can close this full screen Loading.
|
||||
|
||||
If Element is imported entirely, a globally method `$loading` will be registered to Vue.prototype. You can invoke it like this: `this.$loading(options)`, and it also returns a Loading instance.
|
||||
|
||||
### Options
|
||||
|
|
|
@ -204,6 +204,14 @@ Loading.service(options);
|
|||
let loadingInstance = Loading.service(options);
|
||||
loadingInstance.close();
|
||||
```
|
||||
需要注意的是,以服务的方式调用的全屏 Loading 是单例的:若在前一个全屏 Loading 关闭前再次调用全屏 Loading,并不会创建一个新的 Loading 实例,而是返回现有全屏 Loading 的实例:
|
||||
```javascript
|
||||
let loadingInstance1 = Loading.service({ fullscreen: true });
|
||||
let loadingInstance2 = Loading.service({ fullscreen: true });
|
||||
console.log(loadingInstance1 === loadingInstance2); // true
|
||||
```
|
||||
此时调用它们中任意一个的 `close` 方法都能关闭这个全屏 Loading。
|
||||
|
||||
如果完整引入了 Element,那么 Vue.prototype 上会有一个全局方法 `$loading`,它的调用方式为:`this.$loading(options)`,同样会返回一个 Loading 实例。
|
||||
|
||||
### Options
|
||||
|
|
|
@ -12,16 +12,22 @@ const defaults = {
|
|||
customClass: ''
|
||||
};
|
||||
|
||||
let originalPosition, originalOverflow;
|
||||
let fullscreenLoading;
|
||||
|
||||
LoadingConstructor.prototype.originalPosition = '';
|
||||
LoadingConstructor.prototype.originalOverflow = '';
|
||||
|
||||
LoadingConstructor.prototype.close = function() {
|
||||
if (this.fullscreen && originalOverflow !== 'hidden') {
|
||||
document.body.style.overflow = originalOverflow;
|
||||
if (this.fullscreen && this.originalOverflow !== 'hidden') {
|
||||
document.body.style.overflow = this.originalOverflow;
|
||||
}
|
||||
if (this.fullscreen || this.body) {
|
||||
document.body.style.position = originalPosition;
|
||||
document.body.style.position = this.originalPosition;
|
||||
} else {
|
||||
this.target.style.position = originalPosition;
|
||||
this.target.style.position = this.originalPosition;
|
||||
}
|
||||
if (this.fullscreen) {
|
||||
fullscreenLoading = undefined;
|
||||
}
|
||||
this.$el &&
|
||||
this.$el.parentNode &&
|
||||
|
@ -29,13 +35,13 @@ LoadingConstructor.prototype.close = function() {
|
|||
this.$destroy();
|
||||
};
|
||||
|
||||
const addStyle = (options, parent, element) => {
|
||||
const addStyle = (options, parent, instance) => {
|
||||
let maskStyle = {};
|
||||
if (options.fullscreen) {
|
||||
originalPosition = document.body.style.position;
|
||||
originalOverflow = document.body.style.overflow;
|
||||
instance.originalPosition = document.body.style.position;
|
||||
instance.originalOverflow = document.body.style.overflow;
|
||||
} else if (options.body) {
|
||||
originalPosition = document.body.style.position;
|
||||
instance.originalPosition = document.body.style.position;
|
||||
['top', 'left'].forEach(property => {
|
||||
let scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
|
||||
maskStyle[property] = options.target.getBoundingClientRect()[property] +
|
||||
|
@ -47,10 +53,10 @@ const addStyle = (options, parent, element) => {
|
|||
maskStyle[property] = options.target.getBoundingClientRect()[property] + 'px';
|
||||
});
|
||||
} else {
|
||||
originalPosition = parent.style.position;
|
||||
instance.originalPosition = parent.style.position;
|
||||
}
|
||||
Object.keys(maskStyle).forEach(property => {
|
||||
element.style[property] = maskStyle[property];
|
||||
instance.$el.style[property] = maskStyle[property];
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -65,6 +71,9 @@ const Loading = (options = {}) => {
|
|||
} else {
|
||||
options.body = true;
|
||||
}
|
||||
if (options.fullscreen && fullscreenLoading) {
|
||||
return fullscreenLoading;
|
||||
}
|
||||
|
||||
let parent = options.body ? document.body : options.target;
|
||||
let instance = new LoadingConstructor({
|
||||
|
@ -72,14 +81,17 @@ const Loading = (options = {}) => {
|
|||
data: options
|
||||
});
|
||||
|
||||
addStyle(options, parent, instance.$el);
|
||||
if (originalPosition !== 'absolute') {
|
||||
addStyle(options, parent, instance);
|
||||
if (instance.originalPosition !== 'absolute') {
|
||||
parent.style.position = 'relative';
|
||||
}
|
||||
if (options.fullscreen && options.lock) {
|
||||
parent.style.overflow = 'hidden';
|
||||
}
|
||||
parent.appendChild(instance.$el);
|
||||
if (options.fullscreen) {
|
||||
fullscreenLoading = instance;
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
|
|
|
@ -4,10 +4,11 @@ import LoadingRaw from 'packages/loading';
|
|||
const Loading = LoadingRaw.service;
|
||||
|
||||
describe('Loading', () => {
|
||||
let vm, loadingInstance;
|
||||
let vm, loadingInstance, loadingInstance2;
|
||||
afterEach(() => {
|
||||
destroyVM(vm);
|
||||
loadingInstance && loadingInstance.close();
|
||||
loadingInstance2 && loadingInstance2.close();
|
||||
});
|
||||
|
||||
describe('as a directive', () => {
|
||||
|
@ -207,6 +208,21 @@ describe('Loading', () => {
|
|||
expect(mask.classList.contains('is-fullscreen')).to.true;
|
||||
});
|
||||
|
||||
it('fullscreen singleton', done => {
|
||||
loadingInstance = Loading({ fullScreen: true });
|
||||
setTimeout(() => {
|
||||
loadingInstance2 = Loading({ fullScreen: true });
|
||||
setTimeout(() => {
|
||||
let masks = document.querySelectorAll('.el-loading-mask');
|
||||
expect(masks.length).to.equal(1);
|
||||
loadingInstance2.close();
|
||||
masks = document.querySelectorAll('.el-loading-mask');
|
||||
expect(masks.length).to.equal(0);
|
||||
done();
|
||||
}, 100);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it('lock', () => {
|
||||
loadingInstance = Loading({ lock: true });
|
||||
expect(document.body.style.overflow).to.equal('hidden');
|
||||
|
|
Loading…
Reference in New Issue