VUE 爬坑之旅-- 让遮罩层后的内容不可滚动但它上面的容器可正常滚动

在做 webAPP 的时候,经常需要弹出一个对话框,做出一个对话框很简单,这不是本篇文章要说的内容,今天要说的是对话框背后的遮罩层。

在弹出对话框的时候一般都会加一个半透的背景以跟正常页面区分开来,这个背景也很简单,不多说。那么问题来了,加上了半透的背景也即遮罩层之后,如果原来的页面不止一屏,也就是说原来的页面是可滚动的,这时你如果在遮罩层上上下滑动,会发现遮罩层后的页面会跟着滑动,这种事情肯定是不被允许的嘛,那么要怎么解决这个问题呢。

这个问题前人肯定也碰到过,那么他们是怎么解决的呢,在一顿搜索之后,基本上就是二种解决方案,

  1. 弹出对话框时,给遮罩层设置 overflow:hidden 等CSS属性
  2. 用 JS 控制,阻止浏览器原生事件

但是其实这二种方法都是有缺陷的,并不能完全的解决问题,前人也在他们的博客里面详细的说明了,我这里就不再多说。
对上面二种解决方案感兴趣的可以看下这篇博客 https://blog.csdn.net/libin_1/article/details/52614821

由于上面二种解决方案并不能完全解决问题,那么我就继续需求其他的办法,终于,功夫不负有心人,在 移动端滚动穿透问题完美解决方案 这篇博客里面找到了完美的解决方案,而且作者还专门写了一个 Demo 放出来,简直大赞。

解决方案找到了,那么就需要验证下是否真的可行,由于原作者是用传统的方式写的,而我现在要将它用在我的 vue 项目里面,所以需要稍微改造下。具体步骤如下:

在 index.html 文件中加入下面这段 JS 代码

<script type="text/javascript">
    //解决遮罩层滚动穿透问题,分别在遮罩层弹出后和关闭前调用
    const ModalHelper = ( (bodyCls) =>{
        let scrollTop;
        return {
            afterOpen: function () {
                scrollTop = document.scrollingElement.scrollTop;
                document.body.classList.add(bodyCls);
                document.body.style.top = -scrollTop + 'px';
            },
            beforeClose: function () {
                document.body.classList.remove(bodyCls);
                // scrollTop lost after set position:fixed, restore it back.
                document.scrollingElement.scrollTop = scrollTop;
            }
        };
    })('dialog-open');
</script>

为了可以在整个项目中全局使用,我将这段代码写在 index.html 里面,这是一个偷懒的做法,比较正规的做法是将上面那段代码包装成一个全局函数,

在全局 CSS 中加入如下代码

body.dialog-open {
    position: fixed;
    width: 100%;
}

可以看到这里的 dialog-open 就是上面那段 js 代码里面的东西,其实我对上面的那段 JS 代码和这段 css 属性不是很明白,望明白人能够指点下。
如果有朋友还不知道怎么在 vue 项目中引入全局 css 的,可以看我的这篇文章 VUE 爬坑之旅– 如何对公共JS,CSS进行统一管理,全局调用

在vue组件中,对话框弹出和关闭的地方调用上面那段JS代码

对话框弹出后调用

ModalHelper.afterOpen();

对话框关闭前调用

ModalHelper.beforeClose();

通过以上三个步骤就可以解决文章开始时所描述的问题,不仅遮罩层后的页面不会再滚动,同时如果我们的对话框中如果有内容要滚动(比如说活动规则,注册协议等这些长文本),也是能够正常滚动的。Perfect。感谢大佬为我们提供了解决方案。

猜你喜欢

转载自blog.csdn.net/zgh0711/article/details/80368710