Element-UI / scrollbar-width.js

獲取瀏覽器滾動條寬度,一般用於彈出層的時候,設置body的右邊距,防止overflow: hidden的時候元素抖動。

scrollbar-width.js

import Vue from 'vue';

let scrollBarWidth;

export default function() {
  // 如果是服務器端渲染,則瀏覽器滾動條的寬度爲0
  if (Vue.prototype.$isServer) return 0;
  if (scrollBarWidth !== undefined) return scrollBarWidth;

  const outer = document.createElement('div');
  outer.className = 'el-scrollbar__wrap';
  // 強制出現滾動條
  // .el-scrollbar__wrap {
  //   overflow: scroll;
  //   height: 100%
  // }
  outer.style.visibility = 'hidden';
  outer.style.width = '100px';
  outer.style.position = 'absolute';
  outer.style.top = '-9999px';
  document.body.appendChild(outer);
  // https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
  const widthNoScroll = outer.offsetWidth;
  outer.style.overflow = 'scroll';

  const inner = document.createElement('div');
  inner.style.width = '100%';
  outer.appendChild(inner);

  const widthWithScroll = inner.offsetWidth;
  outer.parentNode.removeChild(outer);
  // 父元素出現滾動條,子元素無滾動條,父元素減去子元素的寬度就是滾動條寬度
  scrollBarWidth = widthNoScroll - widthWithScroll;

  return scrollBarWidth;
};

簡單使用

let scrollBarWidth;

export default function() {
  const outer = document.createElement('div');
  outer.style.overflow = 'scroll';
  outer.style.visibility = 'hidden';
  outer.style.width = '100px';
  outer.style.height = '100%';
  outer.style.position = 'absolute';
  outer.style.top = '-9999px';
  document.body.appendChild(outer);
  // https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/offsetWidth
  const widthNoScroll = outer.offsetWidth;

  const inner = document.createElement('div');
  inner.style.width = '100%';
  outer.appendChild(inner);

  const widthWithScroll = inner.offsetWidth;
  outer.parentNode.removeChild(outer);
  // 父元素出現滾動條,子元素無滾動條,父元素減去子元素的寬度就是滾動條寬度
  scrollBarWidth = widthNoScroll - widthWithScroll;

  return scrollBarWidth;
};

彈窗彈出時如果需要鎖屏(鎖住彈窗下的頁面不滾動),則加上下面這段代碼,彈窗彈出時鎖屏,彈窗關閉時再將其去除。

// 如果需要鎖屏(鎖住彈窗下的頁面不滾動)
if (props.lockScroll) {
  // body 上面是否添加 'el-popup-parent--hidden'
  // .el-popup-parent--hidden {
  //     overflow: hidden
  // }
  this.withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden');
  if (this.withoutHiddenClass) {
    // 獲取 body 的 paddingRight
    this.bodyPaddingRight = document.body.style.paddingRight;
    this.computedBodyPaddingRight = parseInt(getStyle(document.body, 'paddingRight'), 10);
  }
  // 獲取滾動條寬
  scrollBarWidth = getScrollBarWidth();
  // body 是否出現滾動條
  let bodyHasOverflow = document.documentElement.clientHeight < document.body.scrollHeight;
  // body 的 overflowY 設置值
  let bodyOverflowY = getStyle(document.body, 'overflowY');
  if (scrollBarWidth > 0 && (bodyHasOverflow || bodyOverflowY === 'scroll') && this.withoutHiddenClass) {
    // body 的 paddingRight 加上 滾動條寬度來實現防止頁面抖動
    document.body.style.paddingRight = this.computedBodyPaddingRight + scrollBarWidth + 'px';
  }
  // body 添加 overflow: hidden
  addClass(document.body, 'el-popup-parent--hidden');
}

彈窗關閉時將彈窗打開時設置的值去除。

if (tthis.withoutHiddenClass) {
  document.body.style.paddingRight = this.bodyPaddingRight;
  removeClass(document.body, 'el-popup-parent--hidden');
}
this.withoutHiddenClass = true;

文中的一些方法可以查看Element-UI / dom.js 的學習

更多內容可查看我的個人博客

發佈了129 篇原創文章 · 獲贊 138 · 訪問量 59萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章