通过新图像预加载图像与链接标签预加载图像有区别吗?

问题描述 投票:0回答:1

使用 Javascript 预加载图像时,使用

new Image()
document.createElement(link)
rel="preload"
之间有区别吗?

例如,以下之间有区别吗:

const loadImage = (src) => 
  new Promise(r => {
    const image = new Image()
    image.onload = r
    image.onerror = r
    image.src = src
  })

const loadImage = (src) =>
  new Promise((resolve, reject) => {
    const link = document.createElement("link")
    link.rel = "preload"
    link.as = "image"
    link.href = src
    link.onload = () => {
      document.head.removeChild(link)
      resolve(undefined)
    }
    link.onerror = reject
    document.head.appendChild(link)
  })

测试时我没有注意到任何事情。我的用例是我想在更新页面之前加载图像,以避免图像加载时出现闪烁。

javascript dom
1个回答
2
投票

没有太大区别,但两者只会在网络请求完成时让您知道。这只是图像工作的一部分。 您会在大图像中注意到这一点,但图像数据的解码也可能需要相当长的时间,并导致某些浏览器中出现一些令人不快的闪烁。
需要明确的是,在加载事件中,您已经有了图像的宽度和高度,因此之后您不会对页面中的框进行奇怪的大小调整,但在某些浏览器中,您可能会看到一个空框有时,甚至在解码图像时出现一些奇怪的故障,或者在解码发生时简单地锁定整个页面。

为了避免这种情况,您可以使用

HTMLImageElement#decode()
方法,该方法将在解码完成后返回 Promise 解析。

在 Firefox 中运行以下代码片段,在“onload”情况下,您应该在图像实际显示之前看到红色框,而在“decode”情况下,它会直接显示。在 Chrome 中,您应该看到“onload”时 JS 间隔被阻塞了近一秒,而“decode()”则仅阻塞了几毫秒:

onload

// a big image
const url = "https://upload.wikimedia.org/wikipedia/commons/c/cf/Black_hole_-_Messier_87.jpg?";
const img = new Image();
img.src = url + Math.random();
let i = 0;
// keep something happening on the screen
const elem = document.querySelector("pre");
const timer = setInterval(() => elem.textContent = i++, 4);
img.onload = (evt) => {
  document.body.append(img);
  // stop the loop after some time
  setTimeout(() => clearTimeout(timer), 10000);
};
img { background: red; height: 150px }
<pre></pre>

decode()

// a big image
const url = "https://upload.wikimedia.org/wikipedia/commons/c/cf/Black_hole_-_Messier_87.jpg?";
const img = new Image();
img.src = url + Math.random();
let i = 0;
// keep something happening on the screen
const elem = document.querySelector("pre");
const timer = setInterval(() => elem.textContent = i++, 4);
img.decode().then((evt) => {
  document.body.append(img);
  // stop the loop after some time
  setTimeout(() => clearTimeout(timer), 10000);
});
img { background: red; height: 150px }
<pre></pre>

© www.soinside.com 2019 - 2024. All rights reserved.