模态框和禁止页面滚动

96
半生不熟_
2017.11.19 02:56 字数 891

问题

今天帮朋友看了一个问题,是要实现点击按钮出现一个弹框以及背景遮罩的功能。

因为项目在用Bootstrap,所以第一想法当然是直接用Bootstrap的模态框,但是奇葩的是一直出现闪退的情况,但之前从来没有遇到这种情况,就去搜了下。

看到大部分人都说一般是因为JS文件发生了冲突,想了想可能项目引入的库有重写模态框的东西,但是试了半天也没有找到是哪个文件,于是决定换一种方式了,因为项目原因,要尽量少用库和插件实现,所以就去搜了搜,发现最简单的方式就是借助overlay自己写样式实现,因为觉得是一个挺common的东西,就简单总结一下。

需求

  • 点击一个按钮弹出提示框
  • 灰色的遮罩层挡住页面内容
  • 被遮罩的内容禁止点击以及页面滚动功能
  • 再次点击按钮提示框消失,启用页面滚动功能

实现

一般做法

屏幕视窗高度是100vh,当body里面承载的内容大于100vh时,屏幕就会出现上下滚动条,要制作这个效果只需要设置html的高度为100%占满屏幕,并且将html的overflow设置为hidden,即可保证页面不可滚动。

但是由于滚动条没有了,宽度变宽,页面内容会整体偏移一点,或多或少会影响用户体验。

更合理的做法

  • 将内容块独立出来,再声明一个 .overlay 结构用来做背景遮罩,优势是,遮罩层可以被复用,任何需要弹窗的场景,都可以直接用 overlay 这个遮罩层。

  • 不允许页面滚动,定义JsstopScrolling()方法,用onoff控制启动和禁用,使用e.preventDefault()方法将通知 Web 浏览器不要执行与事件关联的默认动作(如果存在这样的动作).
    例如,如果 type 属性是 "submit",在事件传播的任意阶段可以调用任意的事件句柄,通过调用该方法,可以阻止提交表单。

<a id="link" href="http://wuliv.com">网站</a>
$('#link').click(function(event){
    event.preventDefault(); // 阻止了a链接href的访问或跳转
})

使用e.stopPropagation()阻止事件冒泡,使用return false阻止元素在浏览器中的默认行为,但请慎用这个功能,虽然自己使用的不多,但看一遍大神如是说,

当你每次调用”return false“的时候,它实际上做了3件事情:
  • event.preventDefault();
  • event.stopPropagation();
  • 停止回调函数执行并立即返回。

具体想研究的小伙伴,可以点击这里 preventDefault()、stopPropagation()、return false 之间的区别

  • HTML代码
<body>
<a class="display_modal" href="#">显示弹窗</a>

  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>
  <p>正文内容</p>

<div class="modal_content">
  这里是弹窗内容
</div>

<div class="overlay"></div>
</body>
  • CSS代码
.overlay{
  display: none;
  position: fixed;
  top: 80px;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,.8);
}

.modal_content{
  display: none;
  margin: 10px auto;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 200px;
  height: 1000px;
  background: #fff;
  z-index: 10;
}

  • Js代码
<script type="text/javascript">
  $(document).ready(function () {
    $('.display_modal').click(function () {
      $('.overlay,.modal_content').fadeOut("fast");
      $('.overlay,.modal_content').show();

      $('body').on('scroll mousewheel touchmove', stopScrolling);
    });

    $('.overlay,.modal_content').click(function () {
      $('.overlay,.modal_content').fadeIn("fast");
      $('.overlay,.modal_content').hide();

      $('body').off('scroll mousewheel touchmove', stopScrolling);
    });
  });

  function stopScrolling (e) {
    e.preventDefault();
    e.stopPropagation();
    return false;
  }

</script>
  • 关于Overlay,由于中文资料不多,找了下英文解释

overlay is described as: Content is clipped and scroll bars are added when necessary. Importantly its also said only to work in Safari or Chrome (ie
WebKit).
This item on WebKit bugzilla suggest it is not long for this world in
any case: WebKit currently has a proprietary CSS overflow value called "overlay"
which is undocumented and as far as I can > tell from reading the code
works exactly like "auto". We should either remove it or rename it to "-webkit-overlay".

更详细的解释,请点击 设置overlay的模态框overlay亲手试一试

这样就可以实现最开始所有需求了。

web前端
Web note ad 1