功能需求:
最近在做报表功能,筛选条件自动吸顶,并且表格表头也要自动吸顶
思路:
首先想到的就是vue的自定义指令(原谅我css学的不好,第一时间没想到position的 sticky属性),既然想到使用自定义指令,那就想想需要实现的思路,实际很简单:
- 主要是获取当前需要吸顶的dom节点,这个vuv的自定义指令会提供对应的参数,如果不明太,可以去看下vue的自定义指令官方文档,很详细。
- 根据滚动的距离判断是否移动到当前需要吸顶的节点,如果已经滚动到当前节点,则给它增加样式:绝对定位元素,至于是相对于屏幕视口(viewport)的位置来指定元素位置,还是使用absolute通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置,这个取决于项目的实际需求
- 如果已经滚动到当前节点之外,则需要还原样式,移除定位
实现:
import type { Directive, App } from 'vue';
const stickyDirective: Directive = {
mounted(el, binding) {
const scrollParent = binding.value.scrollParent
? document.querySelector(binding.value.scrollParent)
: document.body;
el.parent = scrollParent;
const parent = document.querySelector(binding.value.parent);
el.scrollParent = scrollParent;
el.parent = parent;
const elHeight = el.getBoundingClientRect().height;
const elWidth = el.getBoundingClientRect().width;
el.height = elHeight;
el.width = elWidth;
},
updated(el, binding) {
const elTop = el.getBoundingClientRect().top;
// on函数,是封装的监听事件,根据自己的需求适当修改即可
on(el.scrollParent, 'scroll', (): void => {
const scrollTop = el.scrollParent.pageYOffset || el.scrollParent.scrollTop;
if (scrollTop > elTop - (binding.value.top || 0)) {
el.style.position = 'fixed';
el.style.zIndex = '9';
el.style.top = (binding.value.top || 0) + 'px';
el.style.width = el.width + 'px';
el.style.boxShadow =
'0px 9px 28px 8px rgba(0,0,0,0.05), 0px 6px 16px 0px rgba(0,0,0,0.08), 0px 3px 6px -4px rgba(0,0,0,0.12)';
// 因为当前节点脱离文档流,导致吸顶的瞬间,节点之后的内筒瞬间向上移动当前节点高度,有一种跳跃感
// 所以在此设置此节点父级paddingtop
el.parent.style.paddingTop = el.height + 'px';
} else {
el.style.position = 'static';
el.style.boxShadow = 'none';
el.parent.style.paddingTop = 0;
}
});
},
到此基本就实现了一个简单的节点吸顶的功能了。
现在着手实现表格表头的吸顶功能,在这里说下,我的项目中使用的是vben,一个基于antd vue的开箱即用的项目,本质上还是antd vue。
至于表格表头吸顶项目,肯定第一时间去看antd的官方文档Table,看到了这个sticky属性(这时才想起来position的这个属性)。
可以去看下antd vue Table的源码,并不复杂,实际上就是通过position:sticky实现表头的吸顶。
既然知道怎么使用了,直接用在Table的组件上就好,满心欣喜的把sticky属性用上了,结果并没有起作用,第一时间有些懵逼,难道是vben里antd的版本过低,属性不存在,就去看了代码,发现antd版本是3.*是支持sticky属性的,看到这就更懵逼了,明明支持的属性却无法实现需要的功能,那就只能研究下position:sticky这个css属性了,毕竟归根结底是通过它实现的功能。
然后就在mdn,看到了这句话:
这两句话什么意思,就是需要吸顶的节点的父级,包含其祖先直到根节点,不能使用 overflow的hidden
, scroll
, auto
, 或 overlay这四个属性,如果使用,sticky将失效。
以上就是项目中遇到的一些问题,
在这做一个记录,不喜勿喷。