js如何控制一次只加载一张图片,加载完成后再加载下一张
<p>今天看到一个面试题,是关于img图片加载方面的,有必要记录一下。其实关于这个问题,只要知道图片什么时候加载完成就能解决了。</p><h2>通过onload事件判断Img标签加载完成</h2>
<p>实现逻辑:新建一个Image对象实例,为实例对象设置src属性等,在onload事件中添加此实例对象到父元素中,然后将图片地址数组中的第一个元素剔除,继续调用此方法直到存储图片地址的数组为空。</p>
<h3>代码</h3>
<pre><code>const imgArrs = [...]; // 图片地址
const content = document.getElementById('content');
const loadImg = () => {
if (!imgArrs.length)return;
const img = new Image(); // 新建一个Image对象
img.src = imgArrs;
img.setAttribute('class', 'img-item');
img.onload = () => { // 监听onload事件
// setTimeout(() => { // 使用setTimeout可以更清晰的看清实现效果
content.appendChild(img);
imgArrs.shift();
loadImg();
// }, 1000);
}
img.onerror = () => {
// do something here
}
}
loadImg();
</script>
</code></pre>
<h3>实现效果</h3>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_gif/lCQLg02gtibu8sLmicicHuufo4q7mttGJibVouw9ldxWnJyHu9tQgia0aCYnKwQicgozqDttZuVECUewshYHZzZ8YqCw/640?wx_fmt=gif&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1" alt="图片" /></p>
<p>加上 <code>setTimeout</code>后,看到的效果更加明显,我这里加了500毫秒的延迟(录屏软件只支持录制8秒的时间...)</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_gif/lCQLg02gtibu8sLmicicHuufo4q7mttGJibVegNootItj0kRn2bFnkjJiax0jcTicILRvTFMsqDrJm8uupXg6GdssJZQ/640?wx_fmt=gif&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1" alt="图片" /></p>
<p>其实我在网上还看到了一种答案,通过onreadystatechange事件实现监听,于是在我本地调试了一下,发现并不能实现,img实例对象上并没有这个属性方法。查了查MDN,发现目前仅有 <code>XmlHttpRequest</code>对象和 <code>Document</code>对象中存在 <code>onreadystatechange</code>属性,而对于其它元素 <code>onreadystatechange</code>此属性并不存在。</p>
<p><strong>「因此对于其它元素需要慎用 <code>onreadystatechange</code>事件」</strong>。</p>
<p>不过我电脑上目前只有 <code>Chorme</code>和 <code>Safari</code>两种浏览器,对于 <code>onreadystatechange</code>测试的覆盖面不全,所以我上面的结论可能还需要进一步验证才行,感兴趣的掘友可以调试一下~。</p>
<h2>扩展知识</h2>
<h3>img标签是什么时候发送图片资源请求的?</h3>
<ol>
<li>HTML文档渲染解析,如果解析到img标签的src时,浏览器就会立刻开启一个线程去请求图片资源。</li>
<li>动态创建img标签,设置 <code>src</code>属性时,即使这个img标签没有添加到dom元素中,也会立即发送一个请求。</li>
</ol>
<pre><code>// 例1:
const img = new Image();
img.src = 'http://xxxx.com/x/y/z/ccc.png';
</code></pre>
<p>上面的代码如果运行起来后,就会发送请求。 如图:</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibu8sLmicicHuufo4q7mttGJibV5eRtZkyAsQ5aSDNdOcCUj0nSVhib0RTFBV7wZBxEtflDQlHzufib1QfQ/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片" /></p>
<p>再看一个例子:创建了一个 <code>div</code>元素,然后将存放 <code>img标签</code>元素的变量添加到 <code>div</code>元素内,而 <code>div</code>元素此时并不在 <code>dom</code>文档中,页面不会展示该 <code>div</code>元素,那么浏览器会发送请求吗?</p>
<pre><code>// 例2:
const img = `<img src='http://xxxx.com/x/y/z/ccc.png'>`;
const dom = document.createElement('div');
dom.innerHTML = img;
</code></pre>
<p>答案:会请求。如图:</p>
<p><img src="https://www.3bbs.cn/index-diy/img.php?url=https://mmbiz.qpic.cn/mmbiz_png/lCQLg02gtibu8sLmicicHuufo4q7mttGJibVOCRpNfc3UE8elyxuRw75HQSfncjEtcwMqtmicd7XVEmFsI1ywibebajA/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" alt="图片" /></p>
<h3>通过设置css属性能否做到禁止发送图片请求资源?</h3>
<ol>
<li>给 <code>img标签</code>设置样式 <code>display:none</code>或者 <code>visibility: hidden</code>,隐藏 <code>img标签</code>,无法做到禁止发送请求。</li>
</ol>
<pre><code><img src="http://xxx.com/x/sdf.png" style="display: none;">
或者
<img src="http://xxx.com/x/sdf.png" style="visibility: hidden;">
</code></pre>
<ol start="2">
<li>将图片设置为元素的背景图片,但此元素不存在,可以做到禁止发送请求。</li>
</ol>
<pre><code><!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title></title>
<style>
.test {
height: 200px;
background-image: url('http://eb118-file.cdn.bcebos.com/upload/39148b2a545b48bf9b4ee95fd1b7f1eb_1515564089.png?');
}
</style>
</head>
<body>
<div></div>
</body>
</html>
</code></pre>
<p>dom文档中不存在 <code>test</code>元素时,即使设置了背景图片,也不会发送请求,只有 <code>test</code>元素存在时才会发送请求。</p>
<p>另外这个例子其实有点不太贴切,<code>img标签</code>和 <code>background-image</code>二者有着本质的区别。一个属于HTML标签,另一个属于css样式,加载机制和解析顺序也不同。</p>
<blockquote>
<p>❝一个完整的页面是由 <code>js</code>、<code>html</code>、<code>css</code>组成的,按照解析机制,<code>html</code>元素会优先解析,尽管 <code>css</code>样式是放在 <code>head</code>标签内的,但也不意味着它会优先加载,它只有等到 <code>html</code>文档加载完成后才会执行。而 <code>img标签</code>属于网页内容,所以 <code>img标签</code>会随着网页解析渲染优先于 <code>css样式表</code>加载出来。❞</p>
</blockquote>
页:
[1]