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);
|
let loadingInstance = Loading.service(options);
|
||||||
loadingInstance.close();
|
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.
|
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
|
### Options
|
||||||
|
|
|
@ -204,6 +204,14 @@ Loading.service(options);
|
||||||
let loadingInstance = Loading.service(options);
|
let loadingInstance = Loading.service(options);
|
||||||
loadingInstance.close();
|
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 实例。
|
如果完整引入了 Element,那么 Vue.prototype 上会有一个全局方法 `$loading`,它的调用方式为:`this.$loading(options)`,同样会返回一个 Loading 实例。
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
|
@ -12,16 +12,22 @@ const defaults = {
|
||||||
customClass: ''
|
customClass: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
let originalPosition, originalOverflow;
|
let fullscreenLoading;
|
||||||
|
|
||||||
|
LoadingConstructor.prototype.originalPosition = '';
|
||||||
|
LoadingConstructor.prototype.originalOverflow = '';
|
||||||
|
|
||||||
LoadingConstructor.prototype.close = function() {
|
LoadingConstructor.prototype.close = function() {
|
||||||
if (this.fullscreen && originalOverflow !== 'hidden') {
|
if (this.fullscreen && this.originalOverflow !== 'hidden') {
|
||||||
document.body.style.overflow = originalOverflow;
|
document.body.style.overflow = this.originalOverflow;
|
||||||
}
|
}
|
||||||
if (this.fullscreen || this.body) {
|
if (this.fullscreen || this.body) {
|
||||||
document.body.style.position = originalPosition;
|
document.body.style.position = this.originalPosition;
|
||||||
} else {
|
} else {
|
||||||
this.target.style.position = originalPosition;
|
this.target.style.position = this.originalPosition;
|
||||||
|
}
|
||||||
|
if (this.fullscreen) {
|
||||||
|
fullscreenLoading = undefined;
|
||||||
}
|
}
|
||||||
this.$el &&
|
this.$el &&
|
||||||
this.$el.parentNode &&
|
this.$el.parentNode &&
|
||||||
|
@ -29,13 +35,13 @@ LoadingConstructor.prototype.close = function() {
|
||||||
this.$destroy();
|
this.$destroy();
|
||||||
};
|
};
|
||||||
|
|
||||||
const addStyle = (options, parent, element) => {
|
const addStyle = (options, parent, instance) => {
|
||||||
let maskStyle = {};
|
let maskStyle = {};
|
||||||
if (options.fullscreen) {
|
if (options.fullscreen) {
|
||||||
originalPosition = document.body.style.position;
|
instance.originalPosition = document.body.style.position;
|
||||||
originalOverflow = document.body.style.overflow;
|
instance.originalOverflow = document.body.style.overflow;
|
||||||
} else if (options.body) {
|
} else if (options.body) {
|
||||||
originalPosition = document.body.style.position;
|
instance.originalPosition = document.body.style.position;
|
||||||
['top', 'left'].forEach(property => {
|
['top', 'left'].forEach(property => {
|
||||||
let scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
|
let scroll = property === 'top' ? 'scrollTop' : 'scrollLeft';
|
||||||
maskStyle[property] = options.target.getBoundingClientRect()[property] +
|
maskStyle[property] = options.target.getBoundingClientRect()[property] +
|
||||||
|
@ -47,10 +53,10 @@ const addStyle = (options, parent, element) => {
|
||||||
maskStyle[property] = options.target.getBoundingClientRect()[property] + 'px';
|
maskStyle[property] = options.target.getBoundingClientRect()[property] + 'px';
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
originalPosition = parent.style.position;
|
instance.originalPosition = parent.style.position;
|
||||||
}
|
}
|
||||||
Object.keys(maskStyle).forEach(property => {
|
Object.keys(maskStyle).forEach(property => {
|
||||||
element.style[property] = maskStyle[property];
|
instance.$el.style[property] = maskStyle[property];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,6 +71,9 @@ const Loading = (options = {}) => {
|
||||||
} else {
|
} else {
|
||||||
options.body = true;
|
options.body = true;
|
||||||
}
|
}
|
||||||
|
if (options.fullscreen && fullscreenLoading) {
|
||||||
|
return fullscreenLoading;
|
||||||
|
}
|
||||||
|
|
||||||
let parent = options.body ? document.body : options.target;
|
let parent = options.body ? document.body : options.target;
|
||||||
let instance = new LoadingConstructor({
|
let instance = new LoadingConstructor({
|
||||||
|
@ -72,14 +81,17 @@ const Loading = (options = {}) => {
|
||||||
data: options
|
data: options
|
||||||
});
|
});
|
||||||
|
|
||||||
addStyle(options, parent, instance.$el);
|
addStyle(options, parent, instance);
|
||||||
if (originalPosition !== 'absolute') {
|
if (instance.originalPosition !== 'absolute') {
|
||||||
parent.style.position = 'relative';
|
parent.style.position = 'relative';
|
||||||
}
|
}
|
||||||
if (options.fullscreen && options.lock) {
|
if (options.fullscreen && options.lock) {
|
||||||
parent.style.overflow = 'hidden';
|
parent.style.overflow = 'hidden';
|
||||||
}
|
}
|
||||||
parent.appendChild(instance.$el);
|
parent.appendChild(instance.$el);
|
||||||
|
if (options.fullscreen) {
|
||||||
|
fullscreenLoading = instance;
|
||||||
|
}
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,11 @@ import LoadingRaw from 'packages/loading';
|
||||||
const Loading = LoadingRaw.service;
|
const Loading = LoadingRaw.service;
|
||||||
|
|
||||||
describe('Loading', () => {
|
describe('Loading', () => {
|
||||||
let vm, loadingInstance;
|
let vm, loadingInstance, loadingInstance2;
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
destroyVM(vm);
|
destroyVM(vm);
|
||||||
loadingInstance && loadingInstance.close();
|
loadingInstance && loadingInstance.close();
|
||||||
|
loadingInstance2 && loadingInstance2.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('as a directive', () => {
|
describe('as a directive', () => {
|
||||||
|
@ -207,6 +208,21 @@ describe('Loading', () => {
|
||||||
expect(mask.classList.contains('is-fullscreen')).to.true;
|
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', () => {
|
it('lock', () => {
|
||||||
loadingInstance = Loading({ lock: true });
|
loadingInstance = Loading({ lock: true });
|
||||||
expect(document.body.style.overflow).to.equal('hidden');
|
expect(document.body.style.overflow).to.equal('hidden');
|
||||||
|
|
Loading…
Reference in New Issue