代码之家  ›  专栏  ›  技术社区  ›  Boris Guéry

javascript预加载如何工作?

  •  6
  • Boris Guéry  · 技术社区  · 15 年前

    我不想知道预加载图像的方法,我在网上发现了很多,但我想知道它是如何工作的。 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 回复  |  直到 12 年前
        1
  •  11
  •   Community Sam Holder    7 年前

    您的基本javascript预加载程序执行以下操作:

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

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

    一个有趣的发现 in this question 是当您有一组图像,并尝试使用相同的图像对象预加载所有图像时发生的情况:

    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];
    }
    
        2
  •  5
  •   rism    13 年前

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

    其基本思想是,一旦资源被下载,它将在本地存储在客户机上一段时间,这样浏览器就不必在下次需要显示/使用资源时从网络上重新检索资源。

    您的代码可能工作得很好,您只是误解了Fire Bug显示的内容。

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

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

    然后在不清除缓存的情况下重新加载同一页,您仍然可以在Firebug中看到相同数量的请求。

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

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

    如果您查看Fire Bug窗口的底部,您将看到页面大小仍然相同(195KB),但在我的例子中,大部分页面(188KB)是从缓存本地提取的。

    所以缓存工作了,第二次访问谷歌时,我保存了188KB的下载量。

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

    因此,使用缓存的好处并不是杀死所有未来的资源请求,即仍然对网络进行URI查找,而是在可能的情况下,浏览器将从本地缓存中拉出以满足对内容的需要,而不是在网络上四处寻找。

        3
  •  2
  •   DisgruntledGoat    15 年前

    您可能会对“预加载”的概念感到困惑。如果你的HTML中有很多图片 <img src="..."> ,它们不能用javascript预加载,它们只是用页面加载。

    用javascript预加载图像是指加载文档源中还没有的图像,然后在以后显示它们。它们将在第一次呈现页面后加载。它们是预加载的,以便在显示时消除/最小化加载时间,例如在鼠标滚动时更改图像时。

    对于大多数应用程序,使用“css sprites”代替javascript作为预加载的形式通常是更好的实践。所以应该有很多关于这个的问题。

        4
  •  1
  •   Oli    15 年前

    它只需要创建一个新的DOM图像对象并设置 src 属性。没有什么聪明的,阿飞,它一直为我工作。

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

        5
  •  1
  •   Andrew Noyes    15 年前

    循环上的索引仅查找 在第一张照片上。更改为使用 索引:

    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字符串文本语法。此外,大多数现代浏览器提供与 Image() 通过简单地调用DOM标准方法来构造。例如,如果打开google chrome javascript控制台并键入 Image ,这就是你将得到的:

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

    chrome只使用本地的dom方法创建一个image元素。