使用jQuery即时排序和显示Ajax数据

时间:2017-02-13 19:21:02

标签: javascript jquery ajax sorting

我正在进行多次Ajax调用,以检索来自不同提供商的保险报价,目的是汇总和排序结果。我的简化代码如下所示:

for (var i = 0; i < providerList.length; i++) {
	$.ajax({
	   url : "quote-request/"+ providerList[i] +".php",
	   type: "GET",
	   data : formData,
	   dataType:"json",
	   success: function(results) { 
	      $.each(results, function(index, value) {					
	      $("#results").append("<div>" + value["provider-name"] + value["policy-name"] + value["grand-total"] + "</div>");
	      })
	   }
        });
}

产生:

<div id="results">
    <div>ProviderA Policy1 12.34</div>
    <div>ProviderA Policy2 9.50</div>
    <div>ProviderB Policy1 22.76</div>
</div>

但是我希望结果按照 grand-total 的升序排序,因为每个Ajax调用都会完成,所以每个新结果都会自动插入到正确的位置:

<div id="results">
    <div>ProviderA Policy2 9.50</div> 
    <div>ProviderA Policy1 12.34</div>
    <div>ProviderB Policy1 22.76</div>
</div>

我能想到这样做的唯一方法是在每次调用Ajax之后将每个结果保存到一个数组,然后对数组进行排序并输出结果,但是每次新建一个并保持构建和输出相同的数组似乎有点多余报价被检索。有没有更好的方法呢?

为了澄清,最终的脚本将进行大约10次Ajax调用并加载大约40个结果,因此我们不会在这里讨论大型数据集。此外,一个或多个引号可能具有相同的 grand-total ,在这种情况下,首先出现的并不重要。每个报价还有一个唯一标识符 policy-id ,如果这在这里有用的话。

3 个答案:

答案 0 :(得分:2)

是的,如果您可以按顺序直接插入DOM元素,速度会快得多。这可以做到。您实际上可以将DOM用作伪数组,并使用DOM中的data属性来跟踪您的值。您可以编写一个简短的脚本来搜索DOM中的“伪数组”,并找到适当的索引来插入新元素。

这是一个适合您的简短功能。我还用一个计时器上的一些随机数据来嘲笑它,以显示它是如何工作的:

function insertInline(providerName, policyName, grandTotal) {
  var curDomElement;
  var prevDomElement;
  var insertBefore;
  $('#results div').each(function(index) {
    prevDomElement = curDomElement;
    curDomElement = $(this);
    if (parseInt(curDomElement.data('grandtotal')) > grandTotal) {
      insertBefore = curDomElement;
      return false;
    }
  });
  if (insertBefore) {
    $("<div data-grandTotal='" + grandTotal + "'>" + providerName + policyName + grandTotal + "</div>").insertBefore(insertBefore);
  } else {
    $("#results").append("<div data-grandTotal='" + grandTotal + "'>" + providerName + policyName + grandTotal + "</div>");
  }
}

在你的样本中,你会基本上这样使用它:

for (var i = 0; i < providerList.length; i++) {
    $.ajax({
       url : "quote-request/"+ providerList[i] +".php",
       type: "GET",
       data : formData,
       dataType:"json",
       success: function(results) { 
          $.each(results, function(index, value) {
            insertInline(value["provider-name"], value["policy-name"], parseInt(value["grand-total"]));
          })
       }
    });
}

工作样本:https://jsfiddle.net/mspinks/vnofjobu/

答案 1 :(得分:0)

我想到了一些可行的方法。您可以将grand-total(您要排序的项目)分配给每个div中的属性。然后你可以使用jQuery根据grand-total在results div中放置项目。

所以当你得到第一个项目时,你只需将它添加到results div,但你也会给div一个属性(我称之为值,你可以随意调用它)像这样:

<div value='what-grand-total-is'></div>

然后对于所有其他项目,您将获得当前项目的总计,在现有结果列表中运行,对于每个项目,检查总计,如果您遇到一个更大的孩子 - 当前项目的总数,将当前项目放在该子项目之前。

for (var i = 0; i < providerList.length; i++) {
    $.ajax({
       url : "quote-request/"+ providerList[i] +".php",
       type: "GET",
       data : formData,
       dataType:"json",
       success: function(results) { 
          $.each(results, function(index, value) {  

          // no children, so append first time  
          if( $('#results').children.length == 0 ) {    

            // assign attribute value (or whatever name you want) to div
            $("#results").append("<div value=" + value["grand-total"] +">" + value["provider-name"] + value["policy-name"] + value["grand-total"] + "</div>");

          // if there are items in #results
          } else {    
            // assuming this is returned as type integer
            var currentTotal = value["grand-total"];  

            // for every child
            $('#results').children('div').each(function () { 

              // get grand-total from attribute of current div
              var childTotal = this.attr('value');    

              // convert current div's grand total value from string to float, so we can compare values
              childTotal = parseFloat(childTotal);     

              // if the div we're currently at is greater than or equal to the current result total
              if (currentTotal <= childTotal) {        
                // place the current result in front of the div we're at 
                $(this).before("<div value=" + value["grand-total"] +">" + value["provider-name"] + value["policy-name"] + value["grand-total"] + "</div>");                        // place the current result total before the current child
              }
            });
          }
        })
       }
    });
}

这种方法适用于任何数量的AJAX请求,并且通过这种方式,您不必跟踪数组,它可以随时附加数据。

答案 2 :(得分:0)

您可以使用包含html5 data- attrubute的范围标记每个结果:

http://html5doctor.com/html5-custom-data-attributes/

所以你可以像这样创建div:

<div id="results">
    <div data-provider="ProviderA" data-policy="Policy1" data-grandtotal="9.50">ProviderA Policy1 12.34</div>
    <div data-provider="ProviderA" data-policy="Policy2" data-grandtotal="9.50">ProviderA Policy2 9.50</div>
    <div data-provider="ProviderA" data-policy="Policy2" data-grandtotal="22.76" >ProviderB Policy1 22.76</div>
</div>

之后您可以使用此功能检索数据:

var getDataFromDom=function(){
  var resultData=[];

  $("#results").children().each(function(idx,val){
     var result={
       'provider':$(val).data('provider'),
       'policy':$(val).data('policy'),
       'grand-total':parseFloat($(val).data('grandtotal'))
     }

     resultData.push(result);
  });

   return resultData;
}

之后您可以使用Javascript的排序功能对其进行排序: http://www.w3schools.com/jsref/jsref_sort.asp

然后你唯一想到的就是当你点击相应的排序按钮时: *从div获取data-。 *将它们存储到一个数组中。 *使用javascript的sort()函数和正确的回调对它们进行排序。 *删除div中的所有元素。 *迭代数组并将它们附加到div中。

你会没事的。

PS我使用了最新版本的Jquery(3.1.1),如果你使用较早的版本,用data()替换attr()函数,例如。 $(val).data('provider')将为$(val).attr('data-provider')