diff --git a/packages/message-box/src/main.vue b/packages/message-box/src/main.vue index a146d122f..9845e5a5c 100644 --- a/packages/message-box/src/main.vue +++ b/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); }); diff --git a/packages/theme-chalk/src/common/popup.scss b/packages/theme-chalk/src/common/popup.scss index 67a20d787..e1806c9d9 100644 --- a/packages/theme-chalk/src/common/popup.scss +++ b/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; + } +} diff --git a/src/utils/popup/index.js b/src/utils/popup/index.js index aa0030b85..dea16d518 100644 --- a/src/utils/popup/index.js +++ b/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'); + } } } }; diff --git a/src/utils/vue-popper.js b/src/utils/vue-popper.js index 377731108..969830454 100644 --- a/src/utils/vue-popper.js +++ b/src/utils/vue-popper.js @@ -39,7 +39,6 @@ export default { type: Number, default: 35 }, - transition: String, appendToBody: { type: Boolean, default: true diff --git a/test/unit/specs/mixin.vue-popup.spec.js b/test/unit/specs/mixin.vue-popup.spec.js index e1dfce1dd..0eae6af22 100644 --- a/test/unit/specs/mixin.vue-popup.spec.js +++ b/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); });