26 lines
1.4 KiB
TypeScript
26 lines
1.4 KiB
TypeScript
/*** 滚动 / 视口监听:根节点被移出文档后自动摘净监听,避免单页应用里反复挂载累积监听 ***/
|
|
export function watchViewport(root: HTMLElement, host: HTMLElement | Window, handler: () => void): void {
|
|
// —— 状态集中声明 ——
|
|
const run = (): void => {
|
|
if (!root.isConnected) { // 已卸载:一次性摘掉 scroll 与 resize,后续不再进 handler
|
|
host.removeEventListener('scroll', run);
|
|
window.removeEventListener('resize', run);
|
|
return;
|
|
}
|
|
handler();
|
|
};
|
|
host.addEventListener('scroll', run, { passive: true }); // 被动监听:不阻塞滚动
|
|
window.addEventListener('resize', run); // 视口变化会改判定线与可滚距离
|
|
handler(); // 首帧同步一次:刷新时停在页面中段也能得到正确状态
|
|
}
|
|
|
|
/*** 尺寸监听:根节点尺寸变化时重算(视口缩放、侧栏展开、字体变大),脱离文档即自断,不用手动销毁 ***/
|
|
export function trackSize(root: HTMLElement, handler: () => void): void {
|
|
if (typeof ResizeObserver === 'undefined') { window.addEventListener('resize', handler); return; } // 老环境回落:至少跟上视口变化
|
|
const ro = new ResizeObserver(() => {
|
|
if (!root.isConnected) { ro.disconnect(); return; } // 已卸载:断开观察,避免闭包被观察器拽住
|
|
handler();
|
|
});
|
|
ro.observe(root);
|
|
}
|