08月19, 2018

弹窗之滚动条处理(2)

16年的时候写过一篇:弹窗之滚动条处理

现在之所以翻篇写这个,是因为刚好团队中有这个需求,然后我将之前的代码搬运过去。阿里那边的同事在对我的代码进行review的时候,被说了好多次。

主要的问题在于:事件的处理,他们觉得没有必要。后来因为我的测试也确实没有必要。(因为加了事件之后,会衍生出很多很多问题)

另外还有一个问题是给html、body都加上overflow:hidden,会造成页面的抖动(打开弹窗、关闭弹窗)。事实上只要给body加一下就OK了。

还有就是padding-right的处理,之前的代码只考虑了有滚动条的情况。那没有滚动条,为什么要加上滚动条宽度呢?

以及如果之前body就有padding-right这个值,是不是也要处理一下呢?

答案肯定是需要的。

我们来看一下bootrap的modal处理吧:

alt

相关的处理都在这几个函数里面了。

不过我纳闷的是判断页面有没有滚动条为什么不用下面这个函数呢:

function hasScrollbar() {
  return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
}

然后根据bootstrap的源码,整理了一份最新版的scrollHanlder.js

import $ from 'jquery';

let originalBodyPad;

const $body = $(document.body);

// 获取滚动条宽度
function getScrollBarWidth() {
  const scrollDiv = document.createElement('div');
  scrollDiv.className = 'modal-scrollbar-measure';
  $body.append(scrollDiv);
  const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
  $body[0].removeChild(scrollDiv);
  return scrollbarWidth;
}

// 判断是否有滚动条
function hasScrollbar() {
  return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight);
}

function disableScroll() {
  $body.addClass("modal-open"); // 给body加上overflow: hidden
  const scrollbarWidth = getScrollBarWidth();
  const bodyPad = parseInt(($body.css('padding-right') || 0), 10); 
  originalBodyPad = document.body.style.paddingRight || '';
  // 如果有滚动条,才加padding-right,不然不加
  if (hasScrollbar()) $body.css('padding-right', bodyPad + scrollbarWidth);
}

function enableScroll() {
  $body.removeClass("modal-open"); 
  $body.css('padding-right', originalBodyPad);
}

export default {
    disableScroll,
    enableScroll
}
.modal-scrollbar-measure {
  position: absolute;
  top: -9999px;
  width: 50px;
  height: 50px;
  overflow: scroll;
}

.modal-open {
  overflow: hidden;
}

能兼容到IE8。

然后周五的时候,同事又报一个bug给我,说滚动条还会显示出来,经检查,他是两个弹窗同时show出来,理论上应该是在一个弹窗show出来之前,前一个弹窗应该要先hide掉。

最近的收获是在阿里同学讨论问题的时候,从他们的回答中,get到了不少的点,是之前自己所忽视的。996确实累啊!!

本文链接:www.my-fe.pub/post/modal-scroll-control.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。