七夏 发表于 2025-2-5 21:12:56

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 = () =&gt; {
if (!imgArrs.length)return;
const img = new Image(); // 新建一个Image对象
img.src = imgArrs;
img.setAttribute('class', 'img-item');
img.onload = () =&gt; { // 监听onload事件
    // setTimeout(() =&gt; { // 使用setTimeout可以更清晰的看清实现效果
      content.appendChild(img);
      imgArrs.shift();
      loadImg();
    // }, 1000);
}
img.onerror = () =&gt; {
    // do something here
}
}
loadImg();


&lt;/script&gt;
</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&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;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&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;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&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;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 = `&lt;img src='http://xxxx.com/x/y/z/ccc.png'&gt;`;
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&amp;from=appmsg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;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>&lt;img src=&quot;http://xxx.com/x/sdf.png&quot; style=&quot;display: none;&quot;&gt;
或者
&lt;img src=&quot;http://xxx.com/x/sdf.png&quot; style=&quot;visibility: hidden;&quot;&gt;
</code></pre>
<ol start="2">
<li>将图片设置为元素的背景图片,但此元素不存在,可以做到禁止发送请求。</li>
</ol>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang='en'&gt;
&lt;head&gt;
    &lt;meta charset='UTF-8'&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;style&gt;
      .test {
            height: 200px;
            background-image: url('http://eb118-file.cdn.bcebos.com/upload/39148b2a545b48bf9b4ee95fd1b7f1eb_1515564089.png?');
      }
    &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</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]
查看完整版本: js如何控制一次只加载一张图片,加载完成后再加载下一张