소스 검색

Loading: full screen loading is now singleton

Leopoldthecoder 8 년 전
부모
커밋
707a0d5a60
4개의 변경된 파일58개의 추가작업 그리고 14개의 파일을 삭제
  1. 8 0
      examples/docs/en-US/loading.md
  2. 8 0
      examples/docs/zh-CN/loading.md
  3. 25 13
      packages/loading/src/index.js
  4. 17 1
      test/unit/specs/loading.spec.js

+ 8 - 0
examples/docs/en-US/loading.md

@@ -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

+ 8 - 0
examples/docs/zh-CN/loading.md

@@ -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

+ 25 - 13
packages/loading/src/index.js

@@ -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;
 };
 

+ 17 - 1
test/unit/specs/loading.spec.js

@@ -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');