jQuery - 未捕获的TypeError:无法读取未定义的属性“length”

时间:2017-12-11 16:47:49

标签: jquery html json

我有这个JSON - address.json

{
  "province": [
    {
      "id": "1",
      "name": "province1",
      "district": [{
          "districtID": "1",
          "districtName": "district1"
        }
      ]
    }, {
      "id": "2",
      "name": "province2",
      "district": [{
          "districtID": "2",
          "districtName": "district2"
        }, {
          "districtID": "3",
          "districtName": "district3"
        }
      ]
    }
  ]
}

HTML代码

 <label for="addressProvince">State: </label>
 <select id="addressProvince"></select>

Javascript

//Province
$(function(){

    $.getJSON("address.json", function(data) {

        console.log( "success1");


        var provinceCount = data.province.length;
        var provinceList = '<option selected="selected" value="0">- select -</option>';

        for (var i = 0; i < provinceCount; i++) {
             provinceList += "<option value='" + data.province[i].id + "'>" + data.province[i].name + "</option>";
        }
        $("#addressProvince").html(provinceList);

    });
});

    //District  
    $('#addressProvince').on('change', function () {

    var provinceID = $(this).val();

    $.getJSON("address.json", function(data) {

        console.log( "success2");

        var provinceCount = data.province.length;

        for (i = 0; i < provinceCount; i++) {

                if(data.province[i].id == provinceID){

                    console.log("dis case 1 = "+ data.province[i].district.length); //***Problem case 1****

                    console.log("dis case 2 = "+ data[0].province[i].district.length); //***Problem case 2****

                    console.log("dis case 3 = "+ data[0].province[i].district[0].districtName); //***Problem case 3****
                }

        }

    });

});
//End District

如何获得区的长度? 我的Console.log报告错误

案例1报告:

  

未捕获的TypeError:无法读取未定义的属性“长度”

案例2报告:

  

未捕获的TypeError:无法读取未定义的属性“省”

案例3报告:

  

未捕获的TypeError:无法读取未定义的属性“省”

1 个答案:

答案 0 :(得分:2)

第一个建议,一次一件作品。删除'从后端获取内容'位,并创建一个可用于开发的工作JSON存根。例如,使用您提供给我们的JSON代码,并从中创建您的对象。现在,使用该位,编写将迭代新创建的对象的代码。如果你能让这个工作正常工作,那么JSON来自内联变量,PHP设置的静态传递变量或getJSON调用都无关紧要。

接下来要注意的是,为什么每次用户更改省选项时都会重新获取JSON?您已经在数据中包含了这些信息,因此再次获取它会浪费开销。使用你已有的。

第三,虽然你可以使用for循环,但是因为你正在使用jQuery,所以使用$ .each()迭代列表。恕我直言,它的工作原理,似乎更直观一点。总而言之,试试这段代码:

var data = {
  "province": [{
    "id": "1",
    "name": "province1",
    "district": [{
      "districtID": "1",
      "districtName": "district1"
    }]
  }, {
    "id": "2",
    "name": "province2",
    "district": [{
      "districtID": "2",
      "districtName": "district2"
    }, {
      "districtID": "3",
      "districtName": "district3"
    }]
  }]
};

//Province
$(function() {
  // create references to the various els in the DOM.
  var provincePane = $(".provinceSelector");
  var districtPane = $(".districtSelector");
  var addressProvinceEl = $("#addressProvince");
  var addressDistrictEl = $("#addressDistrict");
  // create a blank option, we'll use this as the default el.
  var defaultEl = $("<option>")
                      .prop("selected", true)
                      .val("0")
                      .text("- select -");
                      
  // Insert a copy of that default element into the province select.
  addressProvinceEl.append(defaultEl.clone());

  // Using jQuery's each function, we can loop over every data.province
  $.each(data.province, function(){
    // create an option el for this particular province.
    var optionEl = $("<option>")
                    .val(this.id)
                    .text(this.name);
    // append the option into the select.
    addressProvinceEl.append(optionEl);
  })

  //District  
  addressProvinceEl.on('change', function() {
    // get the value of the currently selected option
    var provID = parseInt(this.value);
    // remove all options but the default option from the district select el
    addressDistrictEl.empty();
    addressDistrictEl.append(defaultEl.clone() );

    // If the user has gone back to '- select -', hide the district pane
    if (provID == 0) {
      districtPane.hide();
    } else {
      // otherwise, display the district pane.
      districtPane.show();
    }
    
    // iterate over the province list, and find the one matching 
    //   the selected option.
    $.each(data.province, function(){
      if(this.id == provID) {
        // We found a match! Now, using the current province, iterate 
        //  over the district list.
        $.each(this.district, function(){
          // create a new option for each district, setting properties...
          var optionEl = $("<option>")
                          .val(this.districtID)
                          .text(this.districtName);
          // ... and append that new option into the district selector.
          addressDistrictEl.append(optionEl);
        })
      }
    })

  });

});
//End District
.districtSelector {
  display: none;
}

label {
  display: inline-block;
  width: 60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="provinceSelector">
  <label for="addressProvince">State: </label>
  <select id="addressProvince"></select>
</div>
<div class="districtSelector">
  <label for="addressDistrict">District: </label>
  <select id="addressDistrict"></select>
</div>

所有这一切,我回到你的代码而不是上面的代码,只需删除getJSON位,将JSON对象保存为数据变量,然后按原样运行代码。我没有在第一个数据选择器(data.province[i].district.length)上得到任何错误,但是其他两个错误输出,因为数据(例如)不是数组 - 它是一个对象。它是一个根级对象,其中只有一个。至少,我认为它是如何运作的。 To see it working as a fiddle ,或者这里是您的代码,没有getJSON()位

var data = {
  "province": [{
    "id": "1",
    "name": "province1",
    "district": [{
      "districtID": "1",
      "districtName": "district1"
    }]
  }, {
    "id": "2",
    "name": "province2",
    "district": [{
      "districtID": "2",
      "districtName": "district2"
    }, {
      "districtID": "3",
      "districtName": "district3"
    }]
  }]
};

//Province
$(function() {
  console.log("success1");


  var provinceCount = data.province.length;
  var provinceList = '<option selected="selected" value="0">- select -</option>';

  for (var i = 0; i < provinceCount; i++) {
    provinceList += "<option value='" + data.province[i].id + "'>" + data.province[i].name + "</option>";
  }
  $("#addressProvince").html(provinceList);

  //District  
  $('#addressProvince').on('change', function() {

    var provinceID = $(this).val();
    console.log("success2");

    var provinceCount = data.province.length;

    for (i = 0; i < provinceCount; i++) {

      if (data.province[i].id == provinceID) {

        console.log("dis case 1 = " + data.province[i].district.length); //***Problem case 1****

        //console.log("dis case 2 = " + data[0].province[i].district.length); //***Problem case 2****

        //console.log("dis case 3 = " + data[0].province[i].district[0].districtName); //***Problem case 3****
      
      for (var j = 0; j < data.province[i].district.length; j++){
        var district = data.province[i].district[j];
        var optionEl = "<option value='"+district.districtID+"' >"+district.districtName+"</option>";
        $("#addressDistrict").append(optionEl);
      }
      }
    }

  });
});
//End District
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="provinceSelector">
  <label for="addressProvince">State: </label>
  <select id="addressProvince"></select>
</div>
<div class="districtSelector">
  <label for="addressDistrict">District: </label>
  <select id="addressDistrict"></select>
</div>