jQuery Ajax等到所有图像都加载完毕

rob*_*obs 37 ajax jquery loading

我正在尝试使用jQuery执行Ajax调用,该调用运行良好.我使用success事件来显示数据.但是,只要加载外部HTML文件,就会触发成功.如果有大图像,它们会在显示后继续加载.有什么方法可以在所有内容完全加载后显示内容吗?这是代码:

$('#divajax').html('<br><div style="text-align: center;"><img src="res/ajax-loader.gif"></div>');
$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
          $('#divajax').html(data);
    }
});
Run Code Online (Sandbox Code Playgroud)

Dan*_*ard 46

@alex写的插件由于某种原因对我不起作用......我无法弄清楚原因.但他的代码确实激励我提出一个更适合我的轻量级解决方案.它使用jquery承诺.请注意,与@alex的插件不同,这不会尝试考虑元素上的背景图像,只考虑img元素.

// Fn to allow an event to fire after all images are loaded
$.fn.imagesLoaded = function () {

    // get all the images (excluding those with no src attribute)
    var $imgs = this.find('img[src!=""]');
    // if there's no images, just return an already resolved promise
    if (!$imgs.length) {return $.Deferred().resolve().promise();}

    // for each image, add a deferred object to the array which resolves when the image is loaded (or if loading fails)
    var dfds = [];  
    $imgs.each(function(){

        var dfd = $.Deferred();
        dfds.push(dfd);
        var img = new Image();
        img.onload = function(){dfd.resolve();}
        img.onerror = function(){dfd.resolve();}
        img.src = this.src;

    });

    // return a master promise object which will resolve when all the deferred objects have resolved
    // IE - when all the images are loaded
    return $.when.apply($,dfds);

}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这样的东西:

$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {
        $('#divajax').html(data).imagesLoaded().then(function(){
            // do stuff after images are loaded here
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

希望这对某人有帮助.

请注意,使用上面的代码,如果其中一个图像错误(例如因为URL错误),则无论如何都会解析承诺并忽略错误.这可能是您想要的,但是,根据您的情况,您可能会想要在图像无法加载时中止您正在执行的操作.在这种情况下,您可以按如下方式替换onerror行:

img.onerror = function(){dfd.reject();}
Run Code Online (Sandbox Code Playgroud)

并抓住这样的错误:

$('#divajax').html(data).imagesLoaded().done(function(){
    // do stuff after all images are loaded successfully here
}).fail(function(){
    // do stuff if any one of the images fails to load
});
Run Code Online (Sandbox Code Playgroud)

  • @MarkEntingh - 你可能对内存泄漏是正确的 - 我不确定.一旦解决了promise,是否有任何引用留给闭包中的Image对象?我不认为有,所以JS应该垃圾收集它.如果您对此感到担心,可以使用在函数外部定义的Image对象数组,并在"then"函数中显式删除它们.注意 - 您说"页面上每个图像的副本" - 只有在将其应用于整个文档时才会出现这种情况 - $(document).imagesLoaded().通常它只是一个小子集,或者只是一个图像. (3认同)
  • 好点@YM_Industries - 我已更新代码以包含您的建议. (2认同)

ale*_*lex 17

你可以使用我的jQuery插件,waitForImages ......

$.ajax({
    cache: false,
    url: 'ajax/content.php',
    success: function(data) {

         $('#divajax').html(data).hide().waitForImages(function() {
             $(this).show();
         });

    }
});
Run Code Online (Sandbox Code Playgroud)

这会将东西加载到元素中,隐藏它,然后在下载img元素加载后重新显示它.


Lyl*_*att 10

您可以将某些内容绑定到加载事件,以了解它们何时完成:

$('<img>').bind('load', function() {
    $(this).appendTo('body');
});
Run Code Online (Sandbox Code Playgroud)

或者你可以使用这个插件.

  • .on()现在明显推荐使用.bind() (5认同)

Aur*_*uau 5

这会分别在每个 img 加载时触发:

$('img').on('load', function() {
      // do something
});
Run Code Online (Sandbox Code Playgroud)

我用了:

var loaded = 0;
$('img').on('load', function() {
   loaded++;
   if(loaded == $('img').length){
      // do something
   }
});
Run Code Online (Sandbox Code Playgroud)