JQ:$(elem).offset().top ,即原生:offsetTop 为 0 的问题

722 阅读2分钟

昨天,主管让我去解决公司官网的懒加载的bug:部分图片懒加载没有生效,部分生效。我愣是一天也没看出原因来,太惭愧了,最后还是屁颠屁颠回去问我家大神。

话不多说上源码:

$(function(){
        if($('.loading_img').length>0){
                function scr_img(){
                        var viewHeight = $(window).height();
                        var scrollHeight = $(window).scrollTop();
                        var cut_height = scrollHeight + viewHeight - 50;
                        $('.loading_img').each(function(index,elem){
                                if(cut_height > $(elem).offset().top && !$(elem).hasClass('finish')){
                                        $(elem).attr('src', $(elem).attr('data-src'));
                                        $(elem).addClass('finish');
                                }
                        });
                }
                scr_img();
                $(window).scroll(function(){
                        scr_img();
                });
        }
});
1.理解源码

懒加载:不是不加载,而是先加载src上的占位图,滑倒到视口了在替换src来加载真的图。

$(window).height() 浏览器当前窗口可视区域高度

$(window).scrollTop() 浏览器滚动条高度

$(elem).offset().top 元素在文档中的位置

在有类名.loading_img 的图片进行懒加载,当 可视区域高度 + 滚动条高度 - 50 大于 元素在文档中的高度时,则把src的地址换成data-src,并且添加类名finish

小白我觉得源码没毛病,挺对的,我还放在了我自己写的页面上,超级正常,没有bug,烧脑。

2.定位问题

找到懒加载没有生效的图片:

(1) ctrl + f 查找这个图片,好家伙 页面有2处图片加载,其中一张没有加 类名.loading_img 进行懒加载,还display:none真是醉了。

image.png

(2)$(elem).offset().top 为 0 的问题

JQ 的 $(elem).offset().top 也就是原生的 offsetTop。

把没有生效的图片存储为全局,打印它的 offsetTop ,它的 元素在文档中的位置 竟然为 0 ,也就是 在文档html的最上面。

image.png

此时立马翻看文档,文档的解释: HTMLElement.offsetTop 为只读属性,它返回当前元素相对于其 [offsetParent元素的顶部内边距的距离。

很好,我没有读懂(呜呜呜...)继续百度。

总结出:

父级、祖先,有 定位,或 dipslay:none ,或 过度,

子元素的offsetTOp就会指向父级(谁有定位,指向这个定位);

dipslay:none 的话,就直接0;

过度和定位效果一样。

image.png

image.png

image.png

那怎么让元素即保持这些css,又要准确获取到该元素在文档的位置 ??

3.解决问题

getBoundingClientRect()返回元素的大小及其相对于视口的位置。 image.png

getBoundingClientRect().top + 滚动条的位置 document.scrollingElement.scrollTop = 该元素在文档的位置: temp1.getBoundingClientRect().top + document.scrollingElement.scrollTop

最后附上修改后的源码:

$(function(){
        if($('.loading_img').length>0){
                function scr_img(){
                        var viewHeight = $(window).height();
                        var scrollHeight = $(window).scrollTop();
                        var cut_height = scrollHeight + viewHeight - 50;
                        $('.loading_img').each(function(index,elem){
                                if(cut_height > elem.getBoundingClientRect().top + scrollHeight && !$(elem).hasClass('finish')){
                                        $(elem).attr('src', $(elem).attr('data-src'));
                                        $(elem).addClass('finish');
                                }
                        });
                }
                scr_img();
                $(window).scroll(function(){
                        scr_img();
                });
        }
});

记录下这次又傻又惭愧的经历,今日文章到这里,我赶紧回去抱大神的大腿,哈哈哈。