Serenader

Learning by sharing

移动端弹窗禁止背景滚动

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import withStyle from 'react-jss';

import c from '../../utils/classnames';

const style = (theme) => ({
  wrapper: {
    position: 'fixed',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: 4,
    background: 'rgba(0, 0, 0, 0.7)',
    display: 'none',
    '&.show': {
      display: 'block',
    },
  },
});

let documentScrollTop = 0;
let bodyScrollTop = 0;

class Modal extends Component {
  componentDidMount() {
    this.disableBackgroundScroll(this.props.show);
  }

  componentWillReceiveProps(props) {
    if (props.show !== this.props.show) {
      this.disableBackgroundScroll(props.show);
    }
  }

  componentWillUnmount() {
    this.disableBackgroundScroll(false);
  }

  disableBackgroundScroll(show) {
    if (show) {
      documentScrollTop = document.documentElement.scrollTop;
      bodyScrollTop = document.body.scrollTop;
      document.body.style.position = 'fixed';
      document.body.style.top = `-${documentScrollTop || bodyScrollTop}px`;
    } else {
      document.body.style.position = 'static';
      if (documentScrollTop) {
        document.documentElement.scrollTop = documentScrollTop;
      }
      if (bodyScrollTop) {
        document.body.scrollTop = bodyScrollTop;
      }
    }
  }

  render() {
    const { classes, show, children } = this.props;
    return (
      <div className={c(classes.wrapper, { show })}>
        {children}
      </div>
    );
  }
}

Modal.propTypes = {
  classes: PropTypes.objectOf(PropTypes.string).isRequired,
  show: PropTypes.bool.isRequired,
  children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]).isRequired,
};

export default withStyle(style)(Modal);