javascript预加载如何工作?

时间:2009-05-13 23:26:46

标签: javascript browser preloader image-preloader

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

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

要改进此代码,我想知道它是如何工作的。

这就是我的所作所为:

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

        });
    }
然后我做了类似的事情:

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

$(document).ready(preloader);

以下是我显示/添加图片的方式:

$("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 个答案:

答案 0 :(得分:11)

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

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

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

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

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

这只会预加载最后一张图像,因为其余部分没有时间预先加载,然后再循环来更改对象的来源。 View an example of this。单击按钮后,您应该能够立即看到第二个图像,但第一个图像必须加载,因为当您尝试查看时,它无法预加载。

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

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

答案 1 :(得分:5)

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

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

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

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

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

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

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

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

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

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

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

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

答案 2 :(得分:2)

您可能会对“预加载”的概念感到困惑。如果您的HTML中包含<img src="...">的大量图片,则无法使用Javascript预加载它们,只需在页面中加载。

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

  

循环上的索引只是看   在第一张图片。改变它使用   指数:

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

    });
}

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

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

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

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

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

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

var image = new Image();

虽然这样可行,但符合DOM的方法是:

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

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

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

Chrome仅使用原生DOM方法创建图片元素。

相关问题