一段element-ui里的代码-获取滚动条宽度

发现

用过vue的朋友,估计都用过element-ui组件,它有个table组件,组件的属性很多,功能也很强大。

其中有一个固定列的功能,很神奇,效果大致如下:

image.png

这种固定列的效果,对内容过多的表格非常实用。

出于好奇其实现原理,我打开了F12分析DOM结构,发现它居然是用三个表格叠加而来的,如下:

image.png

图中绿色代码片段,一个是左边固定列,一个是右边固定列。他们其实是完全一样的,只不过是通过定位叠在一起,再设置超出隐藏即可。

问题

再继续深挖,表格中的固定列是没有滚动条的(蓝框内),而可滚动的表格是有滚动条的(红框)。

那么在编写界面布局样式的时候,就必须知道滚动条的高度的,这样才能确定固定列的位置。

那么,它又是怎么获取浏览器滚动条高度的呢?

源码

接着就是翻阅其源码了,反正也是开源项目,技术都是可借鉴的。

// element-ui\lib\utils\scrollbar-width.js
import Vue from 'vue';

let scrollBarWidth;

export default function() {
  if (Vue.prototype.$isServer) return 0;
  if (scrollBarWidth !== undefined) return scrollBarWidth;

  const outer = document.createElement('div');
  outer.className = 'el-scrollbar__wrap';
  outer.style.visibility = 'hidden';
  outer.style.width = '100px';
  outer.style.position = 'absolute';
  outer.style.top = '-9999px';
  document.body.appendChild(outer);

  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;
};

这段代码只有几十行,位置在element-ui\lib\utils\scrollbar-width.js,专门用来获取浏览器高度。

源码原理分析

其原理实际上是两个div形成父子关系,并设置其宽度相等,这样一来父级肯定会形成滚动条,而子级没有滚动条。

之后再通过offsetWidth属性获取两个div的宽度差,便是滚动条宽度了。

element这段代码也只能获取body的滚动条尺寸,如果通过css样式`div::-webkit-scrollbar`给特定div设置了滚动条宽度,element是不知道的!

也就是说,你如果给某个div设置了滚动条样式,又在div内部使用了element组件,那么很可能样式会出现错乱,这才是问题的关键!

总结

很简单是不是?

你怎么没想到。



打赏作者

发表评论

电子邮件地址不会被公开。 必填项已用*标注