【问题标题】:jQuery foreach loop orderjQuery foreach 循环顺序
【发布时间】:2016-08-10 16:19:55
【问题描述】:

我有一对选择框,用户必须先选择国家,然后选择该国家的城市或地区:

<select name="ListingCountry" id="ListingCountry">
 <option value="0">-- Choose the country --</option>
 <option value="1" selected="selected">United Kingdom</option>
</select>
<select name="ListingCity" id="ListingCity" class="city">
 <option value="0">-- Choose the city or region --</option>
</select>

第二个&lt;select&gt; 需要根据第一个的选择动态更新 - 即在选择英国时仅显示英国城市和地区。

列表从数据库中生成并设置为数组:

var cityOptions =
{
 1 :
 [
  {
   37: "London",
   1: "Bedfordshire",
   2: "Berkshire",
   3: "Birmingham",
   ...
  }
 ]
};

1 朝顶部引用国家 ID。

ID 号由数据库自动生成。我希望首都始终位于列表的顶部,并通过使用CityOrder 字段并按CityOrder descending 排序在数组打印中实现这一点 - 因此为什么伦敦(使用CityOrder1)尽管 ID 比其他所有人都拥有 CityOrder0 的 ID 更高,但仍位于列表顶部。

然后我使用 jQuery 来动态更新列表:

function updateCityOptions(currentCity)
{
 var $countryAll = $("#ListingCity");
 var $countrySel = $("#ListingCountry option:selected").val();
 if($countrySel!=0)
 {
  $('#ListingCity option:gt(0)').remove();
  $.each(cityOptions[$countrySel], function(k,v)
  {
   $.each(cityOptions[$countrySel][k], function(k2,v2)
   {
    if(k2==currentCity)
    {
     $countryAll.append($('<option selected="selected"></option>').attr("value", k2).text(v2));
    }
    else
    {
     $countryAll.append($('<option></option>').attr("value", k2).text(v2));
    }
   });
  });
  $(".city").fadeIn(300);
 }
 else
 {
  $('#ListingCity option:gt(0)').remove();
  $(".city").fadeOut(300);
 }
}

问题是,选用一个国家/地区的select框的顺序似乎是数组的数字顺序,而不是在DOM中打印它的顺序 - 即在列表中首先出现在列表中(ID 1 号),伦敦在中间的某个地方迷路了。

有什么线索吗?

【问题讨论】:

  • 伦敦是函数参数中的currentCity 吗?您可以只使用.prepend 而不是.append 将其插入&lt;select&gt; 字段的开头。
  • @StuartPinfold,您能否提供一些反馈或接受最适合您的答案?

标签: jquery arrays loops foreach


【解决方案1】:

对象属性未按您期望的顺序存储。当您迭代对象属性时——比如使用$.each,它对对象执行for ... in——顺序将取决于几个因素。首先,这取决于您是否在 ES6 之前的 JavaScript 上运行:那么无法保证任何确定的顺序。

ES6在这方面带来了变化,见"Sort JavaScript Object by Key",当对象属性为数值时,会按数值顺序迭代。

不过,对于所有顺序很重要的列表,我建议使用数组。而不是这个:

{
   37: "London",
   1: "Bedfordshire",
   2: "Berkshire",
   3: "Birmingham",
   ...
}

产生和使用这样的东西:

[
   { id: 37, name: "London"},
   { id: 1, name: "Bedfordshire"},
   { id: 2, name: "Berkshire"},
   { id: 3, name: "Birmingham"},
   ...
]

...并使您的代码适应该结构。

【讨论】:

    【解决方案2】:

    我看了一下,起初认为它应该与其他帖子相似,但是您不按 ID 或名称(文本)排序,而是按其他值排序。为了促进这一点,我创建了一个包含所有国家和城市的对象,然后将它们放入其中。然后我使用 sortOrder 进行排序,该对象作为data-sort 被推送到选项列表中,并使用一个函数进行排序。

    我看到了您的currentCity,但是这可能会随着国家/地区的变化而改变?因此,我通过在城市上放置 isDefault:true 来为每个国家/地区设置“默认值”。

    我也将国家/地区从列表中推了进来,那里有一个默认值。

    这对你的情况来说可能有点矫枉过正,但你可以从中吸取教训。

    创建命名空间

    var myApp = myApp || {};// create a namespace to use. 
    

    添加国家对象:

    myApp.countries = [{
      "name": "United Kingdom",
      isDefault: true,
      id: 1,
      "cities": [{
        id: 1,
        name: "Bedfordshire",
        "sortOrder": 1,
        "isCapital": false
      }, {
        id: 2,
        name: "Berkshire",
        "sortOrder": 2,
        "isCapital": false
      }, {
        id: 3,
        name: "Birmingham",
        "sortOrder": 3,
        "isCapital": false
      }, {
        id: 4,
        name: "Brighton",
        "sortOrder": 4,
        "isCapital": false,
         isDefault:true
      }, {
        id: 5,
        name: "Buckinghamshire",
        "sortOrder": 6,
        "isCapital": false
      }, {
        id: 6,
        name: "Appleton",
        "sortOrder": 5,
        "isCapital": false
      }, {
        id: 37,
        name: "London",
        "sortOrder": 0,
        "isCapital": true
      }]
    }, {
      "name": "Hackem",
      id: 2,
      "cities": [{
        id: 1,
        name: "Somecity",
        "sortOrder": 1,
        "isCapital": false
      }, {
        id: 2,
        name: "Waterton",
        "sortOrder": 2,
        "isCapital": false
      }, {
        id: 3,
        name: "Acre City",
        "sortOrder": 3,
        "isCapital": false
      }, {
        id: 4,
        name: "Jackson",
        "sortOrder": 4,
        "isCapital": false
      }, {
        id: 5,
        name: "Tolkenshire",
        "sortOrder": 6,
        "isCapital": false
      }, {
        id: 6,
        name: "Capital City",
        "sortOrder": 0,
        "isCapital": true
      }, {
        id: 37,
        name: "Paris",
        "sortOrder": 4,
        "isCapital": false
      }]
    }, {
      "name": "NewCountry",
      id: 3,
      "cities": [{
        id: 1,
        name: "Skycity",
        "sortOrder": 1,
        "isCapital": false
      }, {
        id: 2,
        name: "DirtCity",
        "sortOrder": 2,
        "isCapital": false
      }, {
        id: 3,
        name: "Airville",
        "sortOrder": 3,
        "isCapital": false
      }, {
        id: 6,
        name: "Cape Town",
        "sortOrder": 0,
        "isCapital": true
      }, {
        id: 37,
        name: "Walla Walla",
        "sortOrder": 4,
        "isCapital": false
      }]
    }];
    

    将一些函数添加到命名空间以供使用:

    myApp.arrayObj = myApp.arrayObj || {
      lookup: function(myArray, searchTerm, property, firstOnly) {
        var found = [];
        for (var i = 0; i < myArray.length; i++) {
          if (myArray[i][property] === searchTerm) {
            found.push(myArray[i]);
            if (firstOnly) break; //if only the first 
          }
        }
        return found;
      },
      updateCityOptions: function(countries) {
        var $cityAll = $("#ListingCity");
        // lookup by text
        var $countryText = $("#ListingCountry option:selected").text();
        var ac = this.lookup(countries, $countryText, "name", true)[0].cities;
        // lookup by id (alternate approach)
        // var $countryId = $("#ListingCountry option:selected").val();
        // var ac = this.lookup(countries, $countryId , "id", true)[0].cities;
        if (ac) {
          $('#ListingCity option:gt(0)').remove();
          var opt = '<option></option>';
          var newOptions = "";
          $.each(ac, function(k2, v2) {
           // var sel = currentCity == v2.name ? ' selected="selected" ' : "";
            var sel = v2.isDefault ? ' selected="selected" ' : "";
            opt = '<option data-sort="' + v2.sortOrder + '"' + sel + ' value="' + v2.id + '">' + v2.name + '</option>';
            newOptions += opt;
          });
          $cityAll.append(newOptions); //hit the DOM just once
          $cityAll.sortOptions(); // sort what we put in
          $(".city").fadeIn(300);
        } else {
          $cityAll.find('option:gt(0)').remove();
          $(".city").fadeOut(300);
        }
        $cityAll.trigger('change');// because it changed
      },
      setCountries: function(nation) {
        var $countries = $("#ListingCountry");
        $countries.find('option:gt(0)').remove();
        var opt = '';
        var newOptions = "";
        $.each(nation, function(k2, v2) {
          var sel = v2.isDefault ? ' selected="selected" ' : "";
          opt = '<option data-sort="' + v2.sortOrder + '"' + sel + ' value="' + v2.id + '">' + v2.name + '</option>';
          newOptions += opt;
        });
        $countries.append(newOptions); //hit the DOM just once
      }
    };
    

    创建键排序函数:

    // sort the select
    $.fn.sortOptions = function() {
      $(this).each(function() {
        var op = $(this).children("option");
        op.sort(function(a, b) {
          return $(a).data('sort') > $(b).data('sort') ? 1 : -1;
        })
        return $(this).empty().append(op);
      });
    }
    

    启动代码:

    myApp.arrayObj.setCountries(myApp.countries);
    // could be done is way  but we trigger the country change which does this
    // myApp.arrayObj.updateCityOptions(myApp.countries);
    

    处理国家变更事件:

    $('#ListingCountry').on('change', function() {
      myApp.arrayObj.updateCityOptions(myApp.countries);
    }).trigger('change');
    

    编辑:请注意,如果您只想将"isCapital": true 保留为一个,则可以删除所有"isCapital": false,并且它的工作方式相同。

    在这里玩的示例:https://jsfiddle.net/MarkSchultheiss/okk22ovq/2/

    编辑:奖金;备用排序选项

    // sort the select
    $.fn.sortOptionsByText = function() {
      $(this).each(function() {
        var op = $(this).children("option");
        op.sort(function(a, b) {
          return a.text > b.text ? 1 : -1;
        })
        return $(this).empty().append(op);
      });
    }
    
    // sort the select
    $.fn.sortOptionsByValue = function() {
      $(this).each(function() {
        var op = $(this).children("option");
        op.sort(function(a, b) {
          return a.value > b.value ? 1 : -1;
        })
        return $(this).empty().append(op);
      });
    }
    
    // sort the select **IF** we had a "mostused" data-mostused value
    // sort the select
    $.fn.sortOptions = function() {
      $(this).each(function() {
        var op = $(this).children("option");
        op.sort(function(a, b) {
          return $(a).data('mostused') > $(b).data('mostused') ? 1 : -1;
        })
        return $(this).empty().append(op);
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-11
      • 2011-07-12
      • 2017-01-20
      • 2020-08-14
      • 2013-05-27
      • 1970-01-01
      • 2016-05-02
      • 2013-01-04
      相关资源
      最近更新 更多