循环遍历Ajax请求的两种方法jQuery然后何时 - 使用哪些?

Isa*_*son 8 javascript ajax jquery infinite-scroll jquery-isotope

我在工作中有一个看似简单的博客项目,我正在尝试将Isotope Jquery(用于布局/过滤/排序),Infinite Scroll以及通过Ajax动态加载所有博客摘录(所以过滤和排序是在用户向下滚动页面之前应用于所有摘录(在此之后,它们被加载到dom然后可访问)).

这个问题主要涉及通过Ajax获取博客文章摘录数据,然后传递给Isotope过滤代码.我不确定这样做的最佳方法,但我目前正在尝试使用ajax请求遍历每个页面(博客文章摘录),然后作为一个整体访问数据.

我遇到了两种不同的方法来遍历ajax请求,每个请求使用then whenjquery语句.第一个是在这个SO答案中使用方法,另一个是简单地将整个then when语句放在一个$.each语句中.

方法1:

  var pageCount = 15;
  var pageCountArray = [];
  for (var i = 1; i != pageCount; ++i) pageCountArray.push(i);

  var deferreds = [];
  $(pageCountArray).each(function() {
    var pageNumber = this;
      deferreds.push(
        $.get('/page/' + pageNumber)
      )

    $.when.apply($, deferreds)
      .then(function(data){
        console.log(data); 
        // this outputs data as a string from the first page, then a list of objects
        console.log(typeof(data));
        // string
        // 13 - object
    });
  });
Run Code Online (Sandbox Code Playgroud)

稍微搁置一下:关于为什么输出一个字符串然后输出对象的任何想法?

方法2:

  var pageCount = 15;
  var pageCountArray = [];
  for (var i = 1; i != pageCount; ++i) pageCountArray.push(i);

  $(pageCountArray).each(function(data) {
    var pageNumber = this;
      $.when(
        $.get('/page/' + pageNumber)
      ).then(function() {
        console.log(data);
        // this outputs 14 strings of data 
        console.log(typeof(data));
        // 14 - string
      })
  });
Run Code Online (Sandbox Code Playgroud)

我还没有弄清楚如何将Ajaxed数据合并到我的同位素过滤器函数中,但我想我首先需要将其解析为HTML.仍然在javascript中站稳脚跟......在这种情况下,这些数据类型(对象与字符串)之一更容易解析成HTML吗?我想这是我答案的关键?

很有必要获得见解.

PS:对于那些可能知道以更好的方式实现这一目标的人来说,可以通过某种方式与Isotope/Infinite Scroll很好地吻合(也许是为了更好地与这些插件配合使用...我已经我的搜索不成功).

PPS:第二种方法感觉更干净......任何人都知道这不是一个好方法(when then.each循环内使用)的原因?

Gor*_*fex 1

哇,这是一个范围很广的问题,难怪没有任何回应。这是一个很大的问题,所以我会尽力提供帮助。我创建了许多网站,其中包括同位素的排序/过滤,同时使用带有无限滚动的 AJAX 预加载,因此这是我已经写出的最简单的示例之一......

首先,我必须提到,使用 David DeSandro 的ImagesLoaded插件,整个事情效果会更好。这主要是因为它允许您将回调函数(事件发生后执行的函数)附加到给定容器中最终图像的加载事件。哇,太啰嗦了。如何更好地表达...它基本上会询问容器,您装载完毕了吗?不?现在怎么样?你满载了吗?好的,请现在执行此功能...

实现后,我将在 onLoad 事件中从这段代码开始,如下所示......

$(function() {

    extendJQ_PreLoad(); //I Will Get To This Function In A Min

    //Use ImagesLoaded Plugin To Control Load Time Sync
    $(container).imagesLoaded(function() {
        cont.isotope({
            itemSelector: ".box", //This is the class I use on all my images to sort
            layoutMode: "masonry",
            isOriginLeft: true,
            isFitWidth: true,
            filter: "*",
            masonry: {
                columnWidth: ".box"
            }
        });
        preLoadNextImgSet(); //I Will Get To This Function In A Min
    });
});
Run Code Online (Sandbox Code Playgroud)

好吧,让我们来分解一下。在出现要排序/过滤/加载和/或处理的图像之前,ImagesLoaded 插件会阻止同位素插件实例化发生。这是第 1 步。第 2 步是开始查看实际的同位素插件实例化。我告诉它使用 Masonry 插件作为其布局样式,然后我传入一个对象文字,其中包含数组键“masonry”下的选项。这里名为 masonry 的数组键与您过去通常使用独立 Masonry 插件(非同位素或 isotope-2)进行的任何实例化相同。

看这里的第 3 步将是我对 的开始调用extendJQ_PreLoad();。这个函数是我编写的,目的是让 JQuery 知道我需要扩展它的核心功能,以便能够预加载我提供给它的任何图像(作为数组)。就像这样...

function extendJQ_PreLoad() {
    $.preloadImages = function(args) {
        for (var i = 0; i < args.length; i++) {
            $("<img />").attr("src", args[i]);
        }
    }    

} //end function
Run Code Online (Sandbox Code Playgroud)

这只是一个简单的迭代器,没什么花哨的,它允许使用与 DOM 相关的巧妙技巧来预加载图像。如果以这种方式加载图像,它会加载到内存中,但不会加载到 DOM 中,这意味着它已加载并隐藏。一旦您将此图像插入到任何位置,它将非常快速地插入,因为它现在已加载到缓存中并等待放置。您可以在此处查看更多相关信息。

最后要查看的是我对预加载函数的调用。这是对 php 文件的一个非常简单的调用,它只是按顺序查找下一组图像(如果有的话)。如果它获取了一些图像,那么它开始将其添加到内存中的临时 div(同样不在 DOM 上可见),并且现在已设置为简单的 DOM 遍历。让我们查看该函数来剖析其功能......

function preLoadNextImgSet() {
    $.post('AjaxController/ajaxPreload_Gallery.php', {currStart: start, currSize: loadSize}, function(data) {
        if(data!="") {
            var y = $(document.createElement("div")).append(data).find("a"),
                found = [];
            y.each(function() {
                found[found.length] = "img/gallery/" + $(this).text();
            });
            $.preloadImages(found);
        }
    });

} //end function
Run Code Online (Sandbox Code Playgroud)

在此示例中,我在浏览器窗口中存在两个来自 JavaScript 的全局变量,我已经声明了这两个变量。Astart和一个loadSize变量。该start变量表示我们当前所在的图像列表中的当前位置,并且该loadSize变量设置每次预加载图像数量的限制。

现在变量已通过函数设置并发送到 PHP 文件中$.post,我们可以使用 PHP 文件按顺序查找适当的图像并将它们加载到内存中等待使用。此处返回给y变量的任何内容都会由函数迭代each,然后预加载。一旦退出此函数范围,虚构的 div 将被删除并发送到垃圾,因为它不被简单迭代使用。

现在可以。这是一段旅程,但我们几乎已经准备好开始最后的方法了。imagesLoaded既然我们知道了这些函数中添加的新功能,那么让我们首先回过头来看看第一个调用在做什么。DOM-Ready 事件中的调用imagesLoaded在其最底部的部分有一个预加载图像的调用......为什么?这是因为一旦页面加载并将初始图像加载到同位素容器中,我们需要页面现在使用此空闲时间开始加载下一组图像。换句话说,一旦图像被放置和排序并高兴地坐在那里,下一批loadSize图像将被加载并等待您放置它们。

现在是最终功能。该函数是一个通用函数,其唯一目的是将当前预加载的图像正式加载到 DOM 中,然后请求加载下一组图像。但是这个函数到底是怎么调用的呢?这就是延迟加载或无限滚动对我们有用的地方。您需要在页面的某个位置添加此功能...

    $(window).scroll(function(){
        scrollTop = $(window).scrollTop(),
        windowHeight = $(window).height(),
        docuHeight = $(document).height();

        //AJAX Data Pull
        if(((scrollTop + windowHeight)+35) >= docuHeight){
            getNextImages();
        } 
    });
Run Code Online (Sandbox Code Playgroud)

这个函数是让无限滚动效果发生的神奇函数。我添加了 35 像素左右的填充(在我的代码中随机添加 +35),因为有时您希望它加载到靠近页面末尾的位置,但不完全加载到页面的实际末尾。

好的,现在这是设置,当我们到达页面末尾时,该函数将像我们提到的那样一般地获取所有下一个图像。我的功能看起来像这样......

function getNextImages() {
    cont = $(container);
    $.post('AjaxController/ajaxPortfolio_Gallery.php', {currStart: start, currSize: loadSize}, function(data) {
        if(data!="") {
            //Append New Photos Inside <a> Element Tag
            var y = $(document.createElement("div")).append(data).find("a");
            cont.append(y);
            //Fix Image Layouts
            cont.imagesLoaded(function() {
                //Feed Isotope Layout The New Items
                cont.isotope("appended", y);
                cont.find("a").css({"opacity":"1"});
            });

        } else { unFilled = false; }
    });
}
Run Code Online (Sandbox Code Playgroud)

我只是简单地包含了该unFilled变量,以便在到达图像末尾时可以设置一个标志。如果没有图像可供显示,您不希望它一直尝试加载。

好吧,那么。这是很多信息,所以我会尽力继续回答尽可能多的问题。