使用JS实现图片懒加载时浏览器重复加载图片的问题求助
解决图片懒加载中的重复加载问题
嘿,这个懒加载导致的图片重复加载问题我之前也碰到过,来给你拆解下原因和解决办法~
问题根源分析
- 多次调用懒加载函数:你提到网站里Safari会重复加载10次,大概率是
lazy()函数被触发了多次(比如滚动事件重复绑定、定时器重复执行)。每次调用都会遍历所有带[data-src]的元素,重新创建Image对象发起请求,哪怕图片已经加载过。 - 缓存未被有效利用:理论上浏览器会缓存已加载的图片,但如果请求发起时缓存还没生效,或者代码没有判断图片是否已加载,就会重复发起请求。你的示例里用
dot.png作为初始src,和目标图片的缓存完全无关,也会导致每次都要请求新的图片资源。
具体解决方案
1. 标记已处理的图片,避免重复操作
每次处理完一张图片后,给它加个标记(比如移除data-src或者添加自定义属性),这样下次调用lazy()时就跳过已经处理过的图片:
function lazy(){ // 只处理未标记的图片 $('[data-src]:not([data-processed])').each(function(){ var $img = $(this); var src = $img.attr('data-src'); var img = new Image(); img.src = src; $(img).on('load', function(){ console.log('loaded',src); $img.attr('src', this.src) .attr('data-processed', true) // 添加已处理标记 .addClass('vis'); }); }); }
2. 维护已加载图片列表,提前复用缓存
可以用一个全局数组记录已经加载过的图片URL,处理前先检查是否已经加载过,直接复用缓存:
// 全局存储已加载的图片URL var loadedImages = []; function lazy(){ $('[data-src]:not([data-processed])').each(function(){ var $img = $(this); var src = $img.attr('data-src'); // 如果已经加载过,直接赋值并标记 if(loadedImages.includes(src)){ $img.attr('src', src) .attr('data-processed', true) .addClass('vis'); return; } var img = new Image(); img.src = src; $(img).on('load', function(){ console.log('loaded',src); loadedImages.push(src); // 加入已加载列表 $img.attr('src', this.src) .attr('data-processed', true) .addClass('vis'); }); }); }
3. 避免lazy()函数被频繁调用
如果是通过滚动事件触发懒加载,一定要用**防抖(debounce)或者节流(throttle)**来限制调用频率,避免短时间内多次触发:
// 防抖函数:指定时间内只执行最后一次 function debounce(func, wait) { let timeout; return function() { const context = this; const args = arguments; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), wait); }; } // 绑定滚动事件时用防抖包装 $(window).on('scroll', debounce(lazy, 200));
如果是定时器触发,也要确保不会重复设置定时器(比如用一个变量标记是否已经设置过)。
4. 针对Safari的缓存优化
Safari对缓存的处理相对严格,要确保你的图片服务器返回正确的缓存响应头(比如Cache-Control: public, max-age=31536000),这样浏览器才能正确识别并复用缓存的图片,减少重复请求。
为什么你的示例里Chrome也会重复加载?
你的示例里3秒后调用一次lazy(),但如果lazy()被多次调用(比如不小心重复绑定了触发逻辑),每次都会重新创建Image对象发起请求,而此时浏览器的缓存可能还没来得及生效,就会出现重复加载的情况。
内容的提问来源于stack exchange,提问作者nbl7
相关产品推荐
相关产品推荐

