jQuery监听窗口resize事件时元素offset计算错误该如何处理?
问题根源
你首次初始化代码执行后,已经通过.css()方法修改了.lw-popout的left属性,后续resize触发时,你获取的offset()是已经被修改过位置的元素的当前偏移值,而非元素在原生文档流中的默认偏移,以此为基准计算自然会得到错误的结果,相当于每次resize都基于上一次修改后的位置重复计算,逻辑陷入死循环。
解决方案
方案1:JS修正逻辑
计算offset前先清除你手动设置的left属性,拿到元素默认的文档偏移后再重新计算赋值,同时给resize事件加节流避免频繁触发导致的性能问题和抖动:
// 节流函数,避免resize频繁触发 function throttle(func, delay) { let timer = null; return function() { if (!timer) { timer = setTimeout(() => { func.apply(this, arguments); timer = null; }, delay); } } } // 封装定位逻辑 function resetPopoutPosition() { const $popout = $('.lw-popout'); // 临时清除手动设置的left属性,获取原生文档偏移 $popout.css('left', 'auto'); const originOffset = $popout.offset(); $popout.css('left', `-${originOffset.left}px`); } // 初始化执行 $(function() { resetPopoutPosition(); }); // resize时执行,100ms节流时长可根据需求调整 $(window).resize(throttle(resetPopoutPosition, 100));
方案2:纯CSS替代(更推荐)
如果你的需求是让元素相对于整个文档定位,不需要依赖父元素的位置,直接给.lw-popout设置position: absolute,同时确保它的所有祖先元素都没有设置position: relative/absolute/fixed/sticky即可,此时元素默认就是相对于整个文档根节点定位,不需要JS动态计算,也天然支持resize适配。
如果父元素确实有定位无法修改,也可以直接用position: fixed,区别是fixed定位的元素不会随页面滚动,固定在视口位置。
内容的提问来源于stack exchange,提问作者Nick Conley
相关产品推荐
相关产品推荐

