Jelajahi Sumber

Popup: lockScroll uses class instead of inline style, remove redundant code (#11114)

* Popup: when popup open, use a class to prevent body scroll

* popup,MessageBox,vue-popper: remove redundant code

* popup: use getStyle to get document body's paddingRight

* Update mixin.vue-popup.spec.js

* Update mixin.vue-popup.spec.js
hetech 7 tahun lalu
induk
melakukan
63844fd845

+ 2 - 12
packages/message-box/src/main.vue

@@ -161,20 +161,10 @@
         this.onClose && this.onClose();
         messageBox.closeDialog(); // 解绑
         if (this.lockScroll) {
-          setTimeout(() => {
-            if (this.modal && this.bodyOverflow !== 'hidden') {
-              document.body.style.overflow = this.bodyOverflow;
-              document.body.style.paddingRight = this.bodyPaddingRight;
-            }
-            this.bodyOverflow = null;
-            this.bodyPaddingRight = null;
-          }, 200);
+          setTimeout(this.restoreBodyStyle, 200);
         }
         this.opened = false;
-
-        if (!this.transition) {
-          this.doAfterClose();
-        }
+        this.doAfterClose();
         setTimeout(() => {
           if (this.action) this.callback(this.action, this);
         });

+ 8 - 0
packages/theme-chalk/src/common/popup.scss

@@ -1,3 +1,5 @@
+@import "../mixins/mixins";
+
 .v-modal-enter {
   animation: v-modal-in .2s ease;
 }
@@ -31,3 +33,9 @@
   opacity: 0.5;
   background: #000;
 }
+
+@include b(popup-parent) {
+  @include m(hidden) {
+    overflow: hidden;
+  }
+}

+ 21 - 70
src/utils/popup/index.js

@@ -2,42 +2,9 @@ import Vue from 'vue';
 import merge from 'element-ui/src/utils/merge';
 import PopupManager from 'element-ui/src/utils/popup/popup-manager';
 import getScrollBarWidth from '../scrollbar-width';
-import { getStyle } from '../dom';
+import { getStyle, addClass, removeClass, hasClass } from '../dom';
 
 let idSeed = 1;
-const transitions = [];
-
-const hookTransition = (transition) => {
-  if (transitions.indexOf(transition) !== -1) return;
-
-  const getVueInstance = (element) => {
-    let instance = element.__vue__;
-    if (!instance) {
-      const textNode = element.previousSibling;
-      if (textNode.__vue__) {
-        instance = textNode.__vue__;
-      }
-    }
-    return instance;
-  };
-
-  Vue.transition(transition, {
-    afterEnter(el) {
-      const instance = getVueInstance(el);
-
-      if (instance) {
-        instance.doAfterOpen && instance.doAfterOpen();
-      }
-    },
-    afterLeave(el) {
-      const instance = getVueInstance(el);
-
-      if (instance) {
-        instance.doAfterClose && instance.doAfterClose();
-      }
-    }
-  });
-};
 
 let scrollBarWidth;
 
@@ -55,10 +22,6 @@ export default {
       type: Boolean,
       default: false
     },
-    transition: {
-      type: String,
-      default: ''
-    },
     openDelay: {},
     closeDelay: {},
     zIndex: {},
@@ -89,12 +52,6 @@ export default {
     }
   },
 
-  created() {
-    if (this.transition) {
-      hookTransition(this.transition);
-    }
-  },
-
   beforeMount() {
     this._popupId = 'popup-' + idSeed++;
     PopupManager.register(this._popupId, this);
@@ -103,19 +60,16 @@ export default {
   beforeDestroy() {
     PopupManager.deregister(this._popupId);
     PopupManager.closeModal(this._popupId);
-    if (this.modal && this.bodyOverflow !== null && this.bodyOverflow !== 'hidden') {
-      document.body.style.overflow = this.bodyOverflow;
-      document.body.style.paddingRight = this.bodyPaddingRight;
-    }
-    this.bodyOverflow = null;
-    this.bodyPaddingRight = null;
+
+    this.restoreBodyStyle();
   },
 
   data() {
     return {
       opened: false,
-      bodyOverflow: null,
       bodyPaddingRight: null,
+      computedBodyPaddingRight: 0,
+      withoutHiddenClass: false,
       rendered: false
     };
   },
@@ -186,17 +140,18 @@ export default {
         }
         PopupManager.openModal(this._popupId, PopupManager.nextZIndex(), this.modalAppendToBody ? undefined : dom, props.modalClass, props.modalFade);
         if (props.lockScroll) {
-          if (!this.bodyOverflow) {
+          this.withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden');
+          if (this.withoutHiddenClass) {
             this.bodyPaddingRight = document.body.style.paddingRight;
-            this.bodyOverflow = document.body.style.overflow;
+            this.computedBodyPaddingRight = parseInt(getStyle(document.body, 'paddingRight'), 10);
           }
           scrollBarWidth = getScrollBarWidth();
           let bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight;
           let bodyOverflowY = getStyle(document.body, 'overflowY');
-          if (scrollBarWidth > 0 && (bodyHasOverflow || bodyOverflowY === 'scroll')) {
-            document.body.style.paddingRight = scrollBarWidth + 'px';
+          if (scrollBarWidth > 0 && (bodyHasOverflow || bodyOverflowY === 'scroll') && this.withoutHiddenClass) {
+            document.body.style.paddingRight = this.computedBodyPaddingRight + scrollBarWidth + 'px';
           }
-          document.body.style.overflow = 'hidden';
+          addClass(document.body, 'el-popup-parent--hidden');
         }
       }
 
@@ -209,9 +164,7 @@ export default {
 
       this.onOpen && this.onOpen();
 
-      if (!this.transition) {
-        this.doAfterOpen();
-      }
+      this.doAfterOpen();
     },
 
     doAfterOpen() {
@@ -245,26 +198,24 @@ export default {
       this.onClose && this.onClose();
 
       if (this.lockScroll) {
-        setTimeout(() => {
-          if (this.modal && this.bodyOverflow !== 'hidden') {
-            document.body.style.overflow = this.bodyOverflow;
-            document.body.style.paddingRight = this.bodyPaddingRight;
-          }
-          this.bodyOverflow = null;
-          this.bodyPaddingRight = null;
-        }, 200);
+        setTimeout(this.restoreBodyStyle, 200);
       }
 
       this.opened = false;
 
-      if (!this.transition) {
-        this.doAfterClose();
-      }
+      this.doAfterClose();
     },
 
     doAfterClose() {
       PopupManager.closeModal(this._popupId);
       this._closing = false;
+    },
+
+    restoreBodyStyle() {
+      if (this.modal && this.withoutHiddenClass) {
+        document.body.style.paddingRight = this.bodyPaddingRight;
+        removeClass(document.body, 'el-popup-parent--hidden');
+      }
     }
   }
 };

+ 0 - 1
src/utils/vue-popper.js

@@ -39,7 +39,6 @@ export default {
       type: Number,
       default: 35
     },
-    transition: String,
     appendToBody: {
       type: Boolean,
       default: true

+ 3 - 2
test/unit/specs/mixin.vue-popup.spec.js

@@ -13,6 +13,7 @@ const Popup = Object.assign({}, VuePopup, {
 describe('Mixin:vue-popup', () => {
   let vm;
   before(() => {
+    document.body.className = '';
     const modals = document.querySelectorAll('.v-modal');
     [].forEach.call(modals, modal => {
       modal &&
@@ -49,13 +50,13 @@ describe('Mixin:vue-popup', () => {
   it('lock scroll', done => {
     vm = createTest(Popup, { modal: true });
     vm.open();
-    expect(document.body.style.overflow).to.equal('hidden');
+    expect(document.body.classList.contains('el-popup-parent--hidden')).to.be.true;
     vm.close();
     destroyVM(vm);
     setTimeout(() => {
       vm = createTest(Popup, { modal: true, lockScroll: false });
       vm.open();
-      expect(document.body.style.overflow).to.not.equal('hidden');
+      expect(document.body.classList.contains('el-popup-parent--hidden')).to.be.false;
       done();
     }, 200);
   });