预加载图片在移动端反而变卡了?
我在做一个移动端的图片画廊,尝试用 new Image().src = url 预加载下一页的图片,结果发现滑动时反而更卡了,FPS 明显掉。是不是预加载太多导致内存压力大?
目前是进入页面就预加载后面 3 张,代码大概这样:
const preloadImages = (urls) => {
urls.slice(0, 3).forEach(url => {
const img = new Image();
img.src = url;
});
};
有没有更合适的预加载策略?或者需要配合 IntersectionObserver 延迟加载吗?
你当前的策略是每次预加载3张图片,这本身没问题,但要考虑一下预加载的时机和条件。可以试试结合 IntersectionObserver 来实现懒加载。这样只有当用户即将看到图片时才开始加载,而不是一上来就把所有可能需要的图片都塞进内存。
下面是一个简单的示例,展示了如何使用 IntersectionObserver 来实现懒加载:
pre class="pure-highlightjs line-numbers">
const lazyLoadImages = () => {
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
}, { threshold: 0.1 });
images.forEach(image => {
imageObserver.observe(image);
});
};
// 在页面加载完成后调用
window.addEventListener('load', lazyLoadImages);
这个方法的好处是,只有当图片进入视口的10%时才会开始加载,这样可以大大减少同时加载的图片数量,提升性能。
另外,确保图片已经经过优化,比如压缩大小和选择合适的格式,这对移动端性能也有很大帮助。有时候,一张图片哪怕只减少几百KB,对移动设备来说都是一个不小的负担。
建议改成懒加载+可视区域预加载组合拳:
几个关键点:
1. 初始用data-src占位,别直接写src
2. 看到当前图片时,才加载它和下一张
3. rootMargin调大点让预加载更顺滑
安全提醒:移动端一定要控制并发数,我见过有人无脑预加载10张图把APP搞崩溃的。还有记得监控内存警告事件,必要时释放资源:
这方案在项目实测过,千元机上也能保持50+ FPS。不过如果你的画廊是横向滑动,可能要把nextElementSibling改成取右侧兄弟节点。