javascript预加载如何工作?

时间:2022-12-03 22:14:38

I don't want to know a way to preload images, I found much on the net, but I want to know how it works. How is javascript able to preload images? I mean, I tried a snippet from here, and even if it works, it doesn't seem to preload images.

我不想知道一种预装图像的方法,我在网上发现了很多,但我想知道它是如何工作的。 javascript如何预加载图片?我的意思是,我从这里尝试了一个片段,即使它有效,它似乎也没有预装图像。

When I check firebug, I can see that the image is loaded twice, once while the preloading, another time when displaying it!

当我检查萤火虫时,我可以看到图像被加载两次,一次是预加载,另一次是显示它!

To improve this code I'd like to know how it works.

为了改进这段代码,我想知道它是如何工作的。

Here is what i do:

这是我做的:

 function preload(arrayOfImages) {
        $(arrayOfImages).each(function(){
            $('<img/>')[0].src = this;
            //(new Image()).src = this;
            alert(this +'  &&   ' + i++);

        });
    }

then i do something like that:

然后我做那样的事情:

preloader = function() {
    preload(myImages);
}

$(document).ready(preloader);

Here is how i display/add the image :

这是我显示/添加图像的方式:

$("li.works").click(function() {
             $("#viewer").children().empty();
             $('#viewer').children().append('<img src=\'images/ref/'+this.firstChild.id+'.jpg\' alt="'+this.firstChild.id+'" \/>')
             $("#viewer").children().fadeIn();

5 个解决方案

#1


Your basic Javascript preloader does this:

您的基本Javascript预加载器执行此操作:

var image = new Image();
image.src = '/path/to/the/image.jpg';

The way it works is simply by creating a new Image object and setting the src of it, the browser is going to go grab the image. We're not adding this particular image to the browser, but when the time comes to show the image in the page via whatever method we have setup, the browser will already have it in its cache and will not go fetch it again. I can't really tell you why whatever you have isn't working this way without looking at the code, though.

它的工作方式只是创建一个新的Image对象并设置它的src,浏览器将抓住图像。我们没有将这个特定的图像添加到浏览器中,但是当我们通过我们设置的任何方法在页面中显示图像时,浏览器已经将其放在缓存中并且不会再次获取它。我不能真正告诉你为什么你所拥有的不是在没有查看代码的情况下以这种方式工作。

One interesting gotcha that is discussed in this question is what happens when you have an array of images and try preloading them all by using the same Image object:

在这个问题中讨论的一个有趣的问题是当你有一个图像数组并尝试使用相同的Image对象预加载它们时会发生什么:

var images = ['image1.jpg','image2.jpg'];
var image = new Image();
for(var x = 0; x < images.length; x++) {
    image.src = images[x];
}

This will only preload the last image as the rest will not have time to preload before the loop comes around again to change the source of the object. View an example of this. You should be able to instantly see the second image once you click on the button, but the first one will have to load as it didn't get a chance to preload when you try to view it.

这将仅预加载最后一个图像,因为其余的图像没有时间预先加载,然后再次循环来更改对象的源。查看此示例。单击按钮后,您应该能够立即看到第二个图像,但第一个图像必须加载,因为当您尝试查看它时,它没有机会预加载。

As such, the proper way to do many at once would be:

因此,一次做多次的正确方法是:

var images = ['image1.jpg','image2.jpg'];
for(var x = 0; x < images.length; x++) {
    var image = new Image();
    image.src = images[x];
}

#2


Javascript preloading works by taking advantage of the caching mechanism used by browsers.

Javascript预加载通过利用浏览器使用的缓存机制来工作。

The basic idea is that once a resource is downloaded, it is stored for a period of time locally on the client machine so that the browser doesn't have to retrieve the resource again from across the net, the next time it is required for display/use by the browser.

基本思想是,一旦下载了资源,它就会在客户端计算机上本地存储一段时间,以便浏览器不必再从网络上再次检索资源,下次需要进行显示时/由浏览器使用。

Your code is probably working just fine and you're just misinterpeting what Fire Bug is displaying.

您的代码可能正常工作,而您只是错误地处理Fire Bug显示的内容。

To test this theory just hit www.google.com with a clean cache. I.e. clear your download history first.

要测试这个理论,只需使用干净的缓存来访问www.google.com。即首先清除下载历史记录。

The first time through everything will likely have a status of 200 OK. Meaning your browser requested the resource and the server sent it. If you look at the bottom on the Fire Bug window it will says how big the page was say 195Kb and how much of that was pulled from cache. In this case 0Kb.

第一次通过一切可能会有200 OK的状态。这意味着您的浏览器请求资源和服务器发送它。如果你看一下Fire Bug窗口的底部,它会显示页面的大小是多少195Kb以及有多少是从缓存中提取的。在这种情况下0Kb。

Then reload the same page without clearing your cache, and you will still see the same number of requests in FireBug.

然后重新加载同一页面而不清除缓存,您仍然会在FireBug中看到相同数量的请求。

The reason for this is simple enough. The page hasn't changed and still needs all the same resources it needed before.

原因很简单。页面没有更改,仍然需要以前所需的所有相同资源。

What is different is that for the majority of these requests the server returned a 304 Not Modified Status, so the browser checked it's cache to see if it already had the resource stored locally, which in this case it did from the previous page load. So the browser just pulled the resource from the local cache.

不同的是,对于大多数这些请求,服务器返回304未修改状态,因此浏览器检查了它的缓存以查看它是否已经在本地存储了资源,在这种情况下它是从上一页加载完成的。所以浏览器只是从本地缓存中提取资源。

If you look at the bottom of the Fire Bug window you will see that page size is still the same (195Kb) but that the majority of it, in my case 188Kb, was pulled locally from cache.

如果您查看Fire Bug窗口的底部,您将看到页面大小仍然相同(195Kb),但是大多数页面大小(在我的情况下为188Kb)是从缓存中本地提取的。

So the cache did work and the second time i hit Google I saved 188Kb of download.

所以缓存确实有效,第二次点击谷歌我保存了188Kb的下载量。

I'm sure you will find the same thing with preloading your images. The request is still made but if the server returns a status of 304 then you will see that the image is in fact just pulled from local cache and not the net.

我相信你会在预装图像时发现同样的事情。仍然会发出请求,但如果服务器返回304的状态,那么您将看到该图像实际上只是从本地缓存而不是网络中提取的。

So with caching, the advantage is NOT that you kill off all future resource requests, i.e. a Uri lookup is still made to the net but rather that if possible the browser will pull from the local cache to satisify the need for the content, rather than run around the net looking for it.

因此,使用缓存,优势并不是你杀死所有未来的资源请求,即Uri查询仍然在网上进行,而是如果可能的话,浏览器将从本地缓存中提取以满足对内容的需求,而不是在网上奔跑寻找它。

#3


You may be confused by the concept of "preloading". If you have a bunch of images in your HTML with <img src="...">, they cannot be preloaded with Javascript, they just load with the page.

您可能会对“预加载”的概念感到困惑。如果您的HTML中有一堆图像使用javascript预加载如何工作?,则无法使用Javascript预加载它们,只需加载页面即可。

Preloading images with Javascript is about loading images not already in the document source, then displaying them later. They are loaded after the page has rendered for the first time. They are preloaded in order to eliminate/minimize loading time when it comes to making them appear, for example when changing an image on mouse rollover.

使用Javascript预加载图像是关于加载文档源中尚未存在的图像,然后再显示它们。它们是在页面首次渲染后加载的。它们是预加载的,以便在出现它们时消除/最小化加载时间,例如在鼠标翻转时更改图像时。

For most applications, it is usually better practice to use "CSS sprites" as a form of preloading, in lieu of Javascript. SO should have a ton of questions on this.

对于大多数应用程序,通常更好的做法是使用“CSS sprites”作为预加载的一种形式,代替Javascript。对此应该有很多问题。

#4


It just involves making a new DOM image object and setting the src attribute. Nothing clever and AFAIK, it has always worked for me.

它只涉及制作一个新的DOM图像对象并设置src属性。没有什么聪明的和AFAIK,它一直对我有用。

Is it possible the second "load" firebug is showing you is it loading it from cache?

是否有可能第二个“加载”firebug显示你是否从缓存中加载它?

#5


The index on the loop is only looking at the first image. Change it to use the index:

循环上的索引仅查看第一个图像。将其更改为使用索引:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(i){   // Note the argument
        $('<img/>')[i].src = this;    // Note the i
        //(new Image()).src = this;
        alert(this +'  &&   ' + i++);

    });
}

Edit: In retrospect, this was wrong and I can see you're trying to create image elements. I don't understand why the index is there at all, there need not be an index. I think the function should look like this:

编辑:回想起来,这是错误的,我可以看到你正在尝试创建图像元素。我不明白为什么索引根本就存在,不需要索引。我认为该函数应如下所示:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img/>').attr('src', this);
    });
}    

And to instantiate it, why not just do this:

并实例化它,为什么不这样做:

$(function () {    // Equivalent to $(document).ready()
    preload(myImages);
});

JavaScript image preloading works because when a DOM element that contains an image is created, the image is downloaded and cached. Even if another request is made when the image is actually rendered from the HTML, the server will send back a 304 (not changed), and the browser will simply load the image from its cache.

JavaScript图像预加载是有效的,因为当创建包含图像的DOM元素时,将下载并缓存图像。即使在实际从HTML呈现图像时发出了另一个请求,服务器也会发回304(未更改),浏览器将只从其缓存中加载图像。

Paolo suggests using the following notation to create an image object:

Paolo建议使用以下表示法来创建图像对象:

var image = new Image();

While this will work, the DOM-compliant way of doing this is:

虽然这会起作用,但符合DOM的方法是:

var image = document.createElement('img');
image.setAttribute('src', 'path/to/image.jpg');

Which is the way it is being done in the script, except it's using jQuery's HTML string literal syntax to do it. Additionally, most modern browsers offer compatibility with the Image() constructor by simply calling DOM-standard methods. For example, if you open up the Google Chrome JavaScript console and type Image, this is what you'll get:

这是在脚本中完成的方式,除了它使用jQuery的HTML字符串文字语法来完成它。此外,大多数现代浏览器通过简单地调用DOM标准方法提供与Image()构造函数的兼容性。例如,如果您打开Goog​​le Chrome JavaScript控制台并输入Image,那么您将获得以下内容:

function Image() {
    return document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
}

Chrome merely uses the native DOM methods to create an image element.

Chrome仅使用本机DOM方法来创建图像元素。

#1


Your basic Javascript preloader does this:

您的基本Javascript预加载器执行此操作:

var image = new Image();
image.src = '/path/to/the/image.jpg';

The way it works is simply by creating a new Image object and setting the src of it, the browser is going to go grab the image. We're not adding this particular image to the browser, but when the time comes to show the image in the page via whatever method we have setup, the browser will already have it in its cache and will not go fetch it again. I can't really tell you why whatever you have isn't working this way without looking at the code, though.

它的工作方式只是创建一个新的Image对象并设置它的src,浏览器将抓住图像。我们没有将这个特定的图像添加到浏览器中,但是当我们通过我们设置的任何方法在页面中显示图像时,浏览器已经将其放在缓存中并且不会再次获取它。我不能真正告诉你为什么你所拥有的不是在没有查看代码的情况下以这种方式工作。

One interesting gotcha that is discussed in this question is what happens when you have an array of images and try preloading them all by using the same Image object:

在这个问题中讨论的一个有趣的问题是当你有一个图像数组并尝试使用相同的Image对象预加载它们时会发生什么:

var images = ['image1.jpg','image2.jpg'];
var image = new Image();
for(var x = 0; x < images.length; x++) {
    image.src = images[x];
}

This will only preload the last image as the rest will not have time to preload before the loop comes around again to change the source of the object. View an example of this. You should be able to instantly see the second image once you click on the button, but the first one will have to load as it didn't get a chance to preload when you try to view it.

这将仅预加载最后一个图像,因为其余的图像没有时间预先加载,然后再次循环来更改对象的源。查看此示例。单击按钮后,您应该能够立即看到第二个图像,但第一个图像必须加载,因为当您尝试查看它时,它没有机会预加载。

As such, the proper way to do many at once would be:

因此,一次做多次的正确方法是:

var images = ['image1.jpg','image2.jpg'];
for(var x = 0; x < images.length; x++) {
    var image = new Image();
    image.src = images[x];
}

#2


Javascript preloading works by taking advantage of the caching mechanism used by browsers.

Javascript预加载通过利用浏览器使用的缓存机制来工作。

The basic idea is that once a resource is downloaded, it is stored for a period of time locally on the client machine so that the browser doesn't have to retrieve the resource again from across the net, the next time it is required for display/use by the browser.

基本思想是,一旦下载了资源,它就会在客户端计算机上本地存储一段时间,以便浏览器不必再从网络上再次检索资源,下次需要进行显示时/由浏览器使用。

Your code is probably working just fine and you're just misinterpeting what Fire Bug is displaying.

您的代码可能正常工作,而您只是错误地处理Fire Bug显示的内容。

To test this theory just hit www.google.com with a clean cache. I.e. clear your download history first.

要测试这个理论,只需使用干净的缓存来访问www.google.com。即首先清除下载历史记录。

The first time through everything will likely have a status of 200 OK. Meaning your browser requested the resource and the server sent it. If you look at the bottom on the Fire Bug window it will says how big the page was say 195Kb and how much of that was pulled from cache. In this case 0Kb.

第一次通过一切可能会有200 OK的状态。这意味着您的浏览器请求资源和服务器发送它。如果你看一下Fire Bug窗口的底部,它会显示页面的大小是多少195Kb以及有多少是从缓存中提取的。在这种情况下0Kb。

Then reload the same page without clearing your cache, and you will still see the same number of requests in FireBug.

然后重新加载同一页面而不清除缓存,您仍然会在FireBug中看到相同数量的请求。

The reason for this is simple enough. The page hasn't changed and still needs all the same resources it needed before.

原因很简单。页面没有更改,仍然需要以前所需的所有相同资源。

What is different is that for the majority of these requests the server returned a 304 Not Modified Status, so the browser checked it's cache to see if it already had the resource stored locally, which in this case it did from the previous page load. So the browser just pulled the resource from the local cache.

不同的是,对于大多数这些请求,服务器返回304未修改状态,因此浏览器检查了它的缓存以查看它是否已经在本地存储了资源,在这种情况下它是从上一页加载完成的。所以浏览器只是从本地缓存中提取资源。

If you look at the bottom of the Fire Bug window you will see that page size is still the same (195Kb) but that the majority of it, in my case 188Kb, was pulled locally from cache.

如果您查看Fire Bug窗口的底部,您将看到页面大小仍然相同(195Kb),但是大多数页面大小(在我的情况下为188Kb)是从缓存中本地提取的。

So the cache did work and the second time i hit Google I saved 188Kb of download.

所以缓存确实有效,第二次点击谷歌我保存了188Kb的下载量。

I'm sure you will find the same thing with preloading your images. The request is still made but if the server returns a status of 304 then you will see that the image is in fact just pulled from local cache and not the net.

我相信你会在预装图像时发现同样的事情。仍然会发出请求,但如果服务器返回304的状态,那么您将看到该图像实际上只是从本地缓存而不是网络中提取的。

So with caching, the advantage is NOT that you kill off all future resource requests, i.e. a Uri lookup is still made to the net but rather that if possible the browser will pull from the local cache to satisify the need for the content, rather than run around the net looking for it.

因此,使用缓存,优势并不是你杀死所有未来的资源请求,即Uri查询仍然在网上进行,而是如果可能的话,浏览器将从本地缓存中提取以满足对内容的需求,而不是在网上奔跑寻找它。

#3


You may be confused by the concept of "preloading". If you have a bunch of images in your HTML with <img src="...">, they cannot be preloaded with Javascript, they just load with the page.

您可能会对“预加载”的概念感到困惑。如果您的HTML中有一堆图像使用javascript预加载如何工作?,则无法使用Javascript预加载它们,只需加载页面即可。

Preloading images with Javascript is about loading images not already in the document source, then displaying them later. They are loaded after the page has rendered for the first time. They are preloaded in order to eliminate/minimize loading time when it comes to making them appear, for example when changing an image on mouse rollover.

使用Javascript预加载图像是关于加载文档源中尚未存在的图像,然后再显示它们。它们是在页面首次渲染后加载的。它们是预加载的,以便在出现它们时消除/最小化加载时间,例如在鼠标翻转时更改图像时。

For most applications, it is usually better practice to use "CSS sprites" as a form of preloading, in lieu of Javascript. SO should have a ton of questions on this.

对于大多数应用程序,通常更好的做法是使用“CSS sprites”作为预加载的一种形式,代替Javascript。对此应该有很多问题。

#4


It just involves making a new DOM image object and setting the src attribute. Nothing clever and AFAIK, it has always worked for me.

它只涉及制作一个新的DOM图像对象并设置src属性。没有什么聪明的和AFAIK,它一直对我有用。

Is it possible the second "load" firebug is showing you is it loading it from cache?

是否有可能第二个“加载”firebug显示你是否从缓存中加载它?

#5


The index on the loop is only looking at the first image. Change it to use the index:

循环上的索引仅查看第一个图像。将其更改为使用索引:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function(i){   // Note the argument
        $('<img/>')[i].src = this;    // Note the i
        //(new Image()).src = this;
        alert(this +'  &&   ' + i++);

    });
}

Edit: In retrospect, this was wrong and I can see you're trying to create image elements. I don't understand why the index is there at all, there need not be an index. I think the function should look like this:

编辑:回想起来,这是错误的,我可以看到你正在尝试创建图像元素。我不明白为什么索引根本就存在,不需要索引。我认为该函数应如下所示:

function preload(arrayOfImages) {
    $(arrayOfImages).each(function () {
        $('<img/>').attr('src', this);
    });
}    

And to instantiate it, why not just do this:

并实例化它,为什么不这样做:

$(function () {    // Equivalent to $(document).ready()
    preload(myImages);
});

JavaScript image preloading works because when a DOM element that contains an image is created, the image is downloaded and cached. Even if another request is made when the image is actually rendered from the HTML, the server will send back a 304 (not changed), and the browser will simply load the image from its cache.

JavaScript图像预加载是有效的,因为当创建包含图像的DOM元素时,将下载并缓存图像。即使在实际从HTML呈现图像时发出了另一个请求,服务器也会发回304(未更改),浏览器将只从其缓存中加载图像。

Paolo suggests using the following notation to create an image object:

Paolo建议使用以下表示法来创建图像对象:

var image = new Image();

While this will work, the DOM-compliant way of doing this is:

虽然这会起作用,但符合DOM的方法是:

var image = document.createElement('img');
image.setAttribute('src', 'path/to/image.jpg');

Which is the way it is being done in the script, except it's using jQuery's HTML string literal syntax to do it. Additionally, most modern browsers offer compatibility with the Image() constructor by simply calling DOM-standard methods. For example, if you open up the Google Chrome JavaScript console and type Image, this is what you'll get:

这是在脚本中完成的方式,除了它使用jQuery的HTML字符串文字语法来完成它。此外,大多数现代浏览器通过简单地调用DOM标准方法提供与Image()构造函数的兼容性。例如,如果您打开Goog​​le Chrome JavaScript控制台并输入Image,那么您将获得以下内容:

function Image() {
    return document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
}

Chrome merely uses the native DOM methods to create an image element.

Chrome仅使用本机DOM方法来创建图像元素。