fix: body scroll when open modal #1472

pull/1534/head
tangjinzhou 5 years ago
parent c86a261bca
commit e4f83939b9

@ -4,7 +4,7 @@ exports[`Modal render correctly 1`] = `
<div>
<div>
<div>
<div>
<div class="ant-modal-root">
<div class="ant-modal-mask"></div>
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
<div role="document" class="ant-modal" style="width: 520px;">
@ -29,7 +29,7 @@ exports[`Modal render correctly 2`] = `
<div>
<div>
<div>
<div>
<div class="ant-modal-root">
<div class="ant-modal-mask"></div>
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
<div role="document" class="ant-modal" style="width: 520px;">
@ -54,7 +54,7 @@ exports[`Modal render without footer 1`] = `
<div>
<div>
<div>
<div>
<div class="ant-modal-root">
<div class="ant-modal-mask"></div>
<div tabindex="-1" role="dialog" class="ant-modal-wrap ">
<div role="document" class="ant-modal" style="width: 520px;">

@ -46,6 +46,8 @@ function offset(el) {
return pos;
}
let cacheOverflow = {};
export default {
mixins: [BaseMixin],
props: initDefaultProps(IDialogPropTypes, {
@ -57,6 +59,7 @@ export default {
destroyOnClose: false,
prefixCls: 'rc-dialog',
getOpenCount: () => null,
focusTriggerAfterClose: true,
}),
data() {
return {
@ -81,16 +84,6 @@ export default {
},
},
// private inTransition: boolean;
// private titleId: string;
// private openTime: number;
// private lastOutSideFocusNode: HTMLElement | null;
// private wrap: HTMLElement;
// private dialog: any;
// private sentinel: HTMLElement;
// private bodyIsOverflowing: boolean;
// private scrollbarWidth: number;
beforeMount() {
this.inTransition = false;
this.titleId = `rcDialogTitle${uuid++}`;
@ -107,7 +100,7 @@ export default {
beforeDestroy() {
const { visible, getOpenCount } = this;
if ((visible || this.inTransition) && !getOpenCount()) {
this.removeScrollingEffect();
this.switchScrollingEffect();
}
clearTimeout(this.timeoutId);
},
@ -118,12 +111,13 @@ export default {
},
updatedCallback(visible) {
const mousePosition = this.mousePosition;
const {mask, focusTriggerAfterClose} = this;
if (this.visible) {
// first show
if (!visible) {
this.openTime = Date.now();
// this.lastOutSideFocusNode = document.activeElement
this.addScrollingEffect();
this.switchScrollingEffect();
// this.$refs.wrap.focus()
this.tryFocus();
const dialogNode = this.$refs.dialog.$el;
@ -139,7 +133,7 @@ export default {
}
} else if (visible) {
this.inTransition = true;
if (this.mask && this.lastOutSideFocusNode) {
if (mask && this.lastOutSideFocusNode && focusTriggerAfterClose) {
try {
this.lastOutSideFocusNode.focus();
} catch (e) {
@ -166,7 +160,7 @@ export default {
this.destroyPopup = true;
}
this.inTransition = false;
this.removeScrollingEffect();
this.switchScrollingEffect();
if (afterClose) {
afterClose();
}
@ -224,6 +218,7 @@ export default {
bodyStyle,
visible,
bodyProps,
forceRender,
} = this;
const dest = {};
if (width !== undefined) {
@ -284,6 +279,7 @@ export default {
ref="dialog"
style={style}
class={cls}
forceRender={forceRender}
onMousedown={this.onDialogMouseDown}
>
<div tabIndex={0} ref="sentinelStart" style={sentinelStyle} aria-hidden="true" />
@ -369,60 +365,50 @@ export default {
// document.body.style.paddingRight = `${this.scrollbarWidth}px`;
// }
// },
addScrollingEffect() {
switchScrollingEffect() {
const { getOpenCount } = this;
const openCount = getOpenCount();
if (openCount !== 1) {
return;
}
switchScrollingEffect();
document.body.style.overflow = 'hidden';
},
removeScrollingEffect() {
const { getOpenCount } = this;
const openCount = getOpenCount();
if (openCount !== 0) {
return;
if (openCount === 1) {
if (cacheOverflow.hasOwnProperty('overflowX')) {
return;
}
cacheOverflow = {
overflowX: document.body.style.overflowX,
overflowY: document.body.style.overflowY,
overflow: document.body.style.overflow,
};
switchScrollingEffect();
// Must be set after switchScrollingEffect
document.body.style.overflow = 'hidden';
} else if (!openCount) {
// IE browser doesn't merge overflow style, need to set it separately
// https://github.com/ant-design/ant-design/issues/19393
if (cacheOverflow.overflow !== undefined) {
document.body.style.overflow = cacheOverflow.overflow;
}
if (cacheOverflow.overflowX !== undefined) {
document.body.style.overflowX = cacheOverflow.overflowX;
}
if (cacheOverflow.overflowY !== undefined) {
document.body.style.overflowY = cacheOverflow.overflowY;
}
cacheOverflow = {};
switchScrollingEffect(true);
}
document.body.style.overflow = '';
switchScrollingEffect(true);
// this.resetAdjustments();
},
// removeScrollingEffect() {
// const { getOpenCount } = this;
// const openCount = getOpenCount();
// if (openCount !== 0) {
// return;
// }
// document.body.style.overflow = '';
// switchScrollingEffect(true);
// // this.resetAdjustments();
// },
close(e) {
this.__emit('close', e);
},
// checkScrollbar() {
// let fullWindowWidth = window.innerWidth;
// if (!fullWindowWidth) {
// // workaround for missing window.innerWidth in IE8
// const documentElementRect = document.documentElement.getBoundingClientRect();
// fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
// }
// this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
// if (this.bodyIsOverflowing) {
// this.scrollbarWidth = getScrollBarSize();
// }
// },
// resetScrollbar() {
// document.body.style.paddingRight = '';
// },
// adjustDialog() {
// if (this.$refs.wrap && this.scrollbarWidth !== undefined) {
// const modalIsOverflowing =
// this.$refs.wrap.scrollHeight > document.documentElement.clientHeight;
// this.$refs.wrap.style.paddingLeft = `${
// !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : ''
// }px`;
// this.$refs.wrap.style.paddingRight = `${
// this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
// }px`;
// }
// },
// resetAdjustments() {
// if (this.$refs.wrap) {
// this.$refs.wrap.style.paddingLeft = this.$refs.wrap.style.paddingLeft = '';
// }
// },
},
render() {
const { prefixCls, maskClosable, visible, wrapClassName, title, wrapProps } = this;
@ -433,7 +419,7 @@ export default {
style.display = null;
}
return (
<div>
<div class={`${prefixCls}-root`}>
{this.getMaskElement()}
<div
tabIndex={-1}

@ -37,6 +37,9 @@ function IDialogPropTypes() {
closeIcon: PropTypes.any,
forceRender: PropTypes.bool,
getOpenCount: PropTypes.func,
// https://github.com/ant-design/ant-design/issues/19771
// https://github.com/react-component/dialog/issues/95
focusTriggerAfterClose: PropTypes.bool,
};
}

@ -3,6 +3,7 @@ import PropTypes from '../_util/vue-types';
const ILazyRenderBoxPropTypes = {
visible: PropTypes.bool,
hiddenClassName: PropTypes.string,
forceRender: PropTypes.bool,
};
export default {

@ -1,3 +1,3 @@
// based on vc-dialog 7.5.5
// based on vc-dialog 7.5.14
import DialogWrap from './DialogWrap';
export default DialogWrap;

Loading…
Cancel
Save