根据火炬图发现频繁调用add和remove
发现问题代码出现在此处
const scrollChange = (y) => {
// ...
if (pageWrapEl && paginationEl) {
let { bottom } = pageWrapEl.getBoundingClientRect();
if (
Math.ceil(bottom) <= document.body.clientHeight - copyRightElHeihgt &&
paginationEl.classList.contains("sticky-bottom")
) {
cancelBottomSticky();
scrollbarsRef.value.setScrollTop(y.scrollTop + paginationEl.offsetHeight);
} else if (
Math.ceil(bottom) - 5 >
document.body.clientHeight - copyRightElHeihgt
) {
makeBottomSticky();
}
}
};
const makeBottomSticky = () => {
paginationEl.classList.add("sticky-bottom");
paginationEl.style.width = `${pageWrapEl.getBoundingClientRect().width}px`;
paginationEl.style.left = `${pageWrapEl.getBoundingClientRect().left}px`;
};
const cancelBottomSticky = () => {
paginationEl.classList.remove("sticky-bottom");
paginationEl.style.width = "100%";
paginationEl.style.left = "0";
};
造成抖动的原因就是频繁的调用scrollChange,而makeBottomSticky和cancelBottomSticky又会频繁地触发scrollChange,造成了死循环。
scrollChange的逻辑就是往上滚动的时候,paginationEl的底部如果超过了copyRightElHeihgt那块区域5px,就会触发makeBottomSticky,如果不超过,则触发cancelBottomSticky,这两个回调主要是给paginationEl添加/删除sticky-bottom样式
.sticky-bottom {
position: fixed;
bottom: 0px;
box-sizing: border-box;
border-top: 1px solid var(--2, #e8e9f8);
background: rgba(255, 255, 255, 0.8);
box-shadow: 0px -3px 8px 0px rgb(119 118 152 / 5%);
backdrop-filter: blur(10px);
z-index: 100;
width: -webkit-fill-available;
padding: 16px 30px !important;
}
可以看出,sticky-bottom的position属性是fixed,意味着它脱离了文档流
因此就知道了抖动的原因:
当往上滚动的时候,触发了makeBottomSticky,makeBottomSticky使paginationEl添加了sticky-bottom样式脱离了文档流,所以整个page.scrollHeight减少了,如果此时page.scrollHeight不足以支撑paginationEl的的底部在copyRightElHeihgt以内5px的话,又会调用cancelBottomSticky删除sticky-bottom,此时paginationEl又回到了文档流,又达成了触发makeBottomSticky的情况。
解决办法:
-
给
paginationEl一个占位div,这样即使它脱离文档流,page.scrollHeight也不会发生改变 -
取消滚事件,采用
Intersection Observer