JavaScript图片预加载模块实现详解

作者:纸飞机时间:2026-10-30 16:08:42浏览:549

本文介绍如何使用JavaScript实现图片预加载模块以提升用户体验。通过封装imageloader.js模块,利用Image对象设置src属性触发加载,结合回调函数处理完成状态,并支持进度显示与超时控制。文章提供基于webpack的打包示例及核心代码逻辑,帮助开发者掌握前端资源加载的最佳实践。

前言

前言

在Web应用开发中,图片资源往往占据大量加载时间。若图片未加载完成,页面可能出现空白或布局错乱,严重影响用户体验。为了解决这一问题,开发者通常采用加载动画作为过渡方案,其核心技术基础即为图片预加载。预加载的原理相对简单:当为JavaScript中的Image对象设置src属性时,浏览器即开始加载该图片。关键在于,必须确保在设置src属性之前,已为Image对象绑定好load、error等事件监听器,以便准确捕获加载状态。

涉及到的内容

涉及到的内容

实现完整的图片预加载功能,通常涉及以下几个核心环节:首先,预加载的目标往往不是单张图片,而是包含多张图片的资源列表。因此,需要将这些图片的URL信息存储在一个数组或对象容器中,并通过遍历该容器来逐一发起加载请求。

其次,当所有图片加载任务完成后,系统需要执行后续的业务逻辑。这通常通过定义一个回调函数来实现,该函数将在所有图片加载成功(或按策略判定完成)后被触发。

最后,为了提供友好的用户反馈,需要实时记录并展示已加载图片的数量。这要求预加载模块具备状态追踪能力,将加载进度动态反映在页面上,例如通过进度条或数字提示。

编码开始

编码开始

注:html和css省略,主要讲解js文件

为了实现代码的复用性和可维护性,我们将图片预加载的核心逻辑封装在一个名为imageloader.js的JavaScript模块中。该模块对外暴露一个统一的接口,供其他业务模块调用。

入口文件配置

项目的入口文件为index.js,其主要职责是引入预加载模块并配置加载参数。入口文件的代码结构如下:


var loadImage = require('./imageloader.js');
loadImage(['./img/rabbit-big.png','./img/face_slogan.png','./img/footer.png'],finish);
//finish是一个所以图片完成加载之后执行的回调函数
function finish(){
 document.body.innerHTML = '完成加载'
 }

以下是imageloader.js模块的具体实现代码:

核心模块实现


'use strict';

/**
 * 预加载图片的函数
 * @param elem 显示加载进度的元素
 * @param images 加载图片的数组或者对象
 * @param callback 全部图片加载完毕后调用的回调函数
 * @param timeout 加载超时的时长
 */
function loadImage(elem,images,callback,timeout){
 //遍历出图片的计数器
 var count = 0;
 //默认全部图片都能成功加载
 var success = true;
 //超时timer的id
 var timerId = 0;
 //默认不会加载超时
 var isTimeout = false;
 //已经加载完成的长度
 var loaded = 0;

 //对图片数组(或对象)进行遍历
 for(var key in images){
 //过滤掉prototype上的属性
 if(!images.hasOwnProperty(key)){
 continue;
 }
 //获得每个图片元素
 //期望每个图片元素是一个object:{src:XXX}
 var item = images[key];
 if(typeof item === "string"){
 item = images[key] = {
 src:item
 }
 }
 //如果格式不满足期望,则进行下一次遍历
 if(!item || !item.src){
 continue;
 }
 //计算+1
 ++ count;
 //设置图片元素的id
 item.id = '__img__' + key + getId();
 //设置图片元素的image,它是一个image对象
 item.image = window[item.id] = new Image();

 doLoad(item);
 }
 //如果计数为0,则直接调用callback
 if(!count){
 callback(success);
 }else if(timeout){//如果设置了最长加载时间
 timerId = setTimeout(onTimeout,timeout)
 }
 /**
 * 真正进行图片预加载的函数
 * @param item 图片元素的对象
 */
 function doLoad(item){
 item.state = 'loading';

 var img = item.image;
 //图片加载成功的一个回调函数
 img.onload = function(){
 //只要有一张出现加载失败,success就会为false
 success = success & true;
 item.state = 'load';
 loaded ++;
 done();

 };
 //图片加载失败的回调函数
 img.onerror = function(){
 success = false;
 item.state = 'error';
 loaded ++;
 done();
 };
 //加载图片
 img.src = item.src;
 /**
 * 每张图片加载完成的回调函数,不论成功还是失败
 */
 function done(){
 //清除绑定的事件
 img.onload = null;
 img.onerror = null;
 try{
 delete window[item.id]
 }catch (e){

 }
 elem.innerHTML = '已加载' + (loaded / count * 100) + '%';
 //当所有图片加载完成并且没有超时的情况,清除定时器,且执行回调函数
 if(count === loaded && !isTimeout){
 clearTimeout(timerId);
 callback(success);
 }
 }
 }

 /**
 * 超时函数
 */
 function onTimeout(){
 isTimeout = true;
 success = false;
 callback(success);
 }

}

var __id = 0;
function getId(){
 return ++ __id;
}
module.exports = loadImage;

本文示例使用webpack进行模块打包。如果读者对webpack打包流程尚不熟悉,可参考相关文档进行学习。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章