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
pull/11144/head
hetech 2018-05-13 12:07:09 +08:00 committed by 杨奕
parent 6289144d84
commit 63844fd845
5 changed files with 34 additions and 85 deletions

View File

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

View File

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

View File

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

View File

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

View File

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