前端开发一百问(动态更新)
第1问:通过 JavaScript 创建新的 img 元素并指定 onload 事件,为什么要在赋值 src 属性之前指定事件处理程序?
在 JavaScript 中创建 img
元素时,在赋值 src 属性之前指定事件处理程序是为了避免竞态条件(race condition)问题。
为什么要先指定事件处理程序
-
避免错过加载事件
- 当设置
img.src
时,浏览器会立即开始加载图片 - 如果图片加载非常快(例如从缓存中加载),可能在你设置
onload
处理器之前就已经完成了加载 - 这种情况下,
onload
事件已经触发并过去了,你定义的处理器将不会被执行
- 当设置
-
确保事件监听器能正常工作
- 先设置事件处理器,再设置src,可以确保无论图片加载多快,都能捕获到
load
事件 - 这是一种预防性编程实践,确保代码在各种情况下都能按预期工作
- 先设置事件处理器,再设置src,可以确保无论图片加载多快,都能捕获到
// ❌ 错误方式:可能错过加载事件
var img = document.createElement("img");
img.src = "https://www.baidu.com/img/bd_logo1.png"; // 图片开始加载
img.onload = function () {console.log("图片加载完成"); // 如果图片加载太快,可能不会执行
};
document.body.appendChild(img);// ✅ 正确方式:确保捕获加载事件
var img = document.createElement("img");
img.onload = function () {console.log("图片加载完成"); // 确保能捕获到加载事件
};
img.src = "https://www.baidu.com/img/bd_logo1.png"; // 现在开始加载
document.body.appendChild(img);
因为涉及向 DOM 中添加新元素,所以必须确保页面已经加载完成。
如果在页面加载完成之前操作 document.body 会导致错误。
注意,下载图片不一定要把<img>元素添加到文档,只要给它设置了src属性就会立即开始下载。
同样的技术也适用于 DOM0 的 Image 对象
在 DOM 出现之前,客户端都使用 Image 对象预先加载图片。
示例:
//使用新Image对象实现图片预加载。
//不把Image放在DOM中
window.onload = function () {var img = new Image();img.onload = function () {console.log("图片加载完成");};img.src = "https://www.baidu.com/img/bd_logo1.png";
};
注意:有些浏览器会把Image对象实现为<img>元素,但并非所有浏览器都这样。
=============================================
未完待续,持续更新。