2013-10-03 161 views
0

我正在寫一個簡單的天氣應用程序,並堅持使用for循環。這個想法是獲得一小部分地點的天氣,並將每個預測加載到它自己的div中。這裏是到目前爲止的代碼:嵌套循環和新的子元素

$(function() { 
    var z = ["location ID1", "location ID2", etc.]; 
    var n = ["location name1", "location name2", etc]; 
    for (j = 0; j<z.length; j++) { 
     weatherQuery = 'SELECT * FROM rss WHERE url="http://xml.weather.yahoo.com/forecastrss/' + z[j] + '_c.xml"'; 
     $('#weatherData').append($('<div/>', {id: 'c' + j})); 
     $('#c' + j + '').append('' + n[j] + ''); 
     var weatherUrl = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent(weatherQuery) + '&format=json'; 
     $.getJSON(weatherUrl + '&callback=?', function (data) { 
      var weatherForecasts = data.query.results.item.forecast; 
      for (i=0; i<weatherForecasts.length; i++) { 
       var code = weatherForecasts[i].code; 
       $('#c' + j + '').append('<table style = border:none><tr><td class = weather-date>' + weatherForecasts[i].day + '</td><td class = weather-icon style = background-position:-' + (61 * code) + 'px 0px></td><td class = weather-min>' + weatherForecasts[i].low + '°</td><td class = weather-max>' + weatherForecasts[i].high + '°</td></tr></table>');    
      } 
     }); 
    } 
}); 

至於我可以告訴螢火蟲,第一部分工程 - 正確的氣象數據被檢索和父DIV正在創建新的div。正確的位置名稱也被附加到每個新的div。如果它跌倒了將天氣數據附加到每個div。在第二個(最後一個)附加語句中標識子div的正確方法是什麼,以便每個div都有一個迭代的天氣數據解析循環?謝謝。

回答

1
for (j = 0; j<z.length; j++) { 
    $.getJSON(..., function (data) { 
     $('#c' + j + '').append(... 

循環執行z.length倍,啓動z.length AJAX請求,並用j等於z.length終止循環完成。然後,很久以後(因爲AJAX中的'A'表示'asyncronous'),請求完成並調用每個回調函數。他們使用j來選擇要將結果追加到哪個div。但是j仍然是z.length,因爲它在循環結束時返回。使用閉包通過變量創建一個函數並不意味着該變量的值從該函數創建的位置被記住;每個功能都有相同的參考j

(其實你沒有關閉,因爲在所有的循環變量ji沒有聲明var,所以他們意外的全局變量。)

你可以記住一個局部變量的值當創建一個函數時,通過將其包含在一個帶有該變量的單獨函數中(或使用ECMAScript 5中的function.bind)。這樣做的一個簡單方法是使用基於回調的功能循環,而不是一個for

var places = [ 
    {id: 'location1', name: 'Location One'}, 
    ... 
]; 

$.each(places, function(place_i, place) { 
    var yql = 'SELECT * FROM rss WHERE url="http://xml.weather.yahoo.com/forecastrss/' + encodeURIComponent(place.id) + '_c.xml"'; 
    var div = $('<div/>').attr('id', 'c'+place_i)).text(place.name); 
    $('#weatherData').append(div); 

    $.ajax({ 
     url: 'http://query.yahooapis.com/v1/public/yql', 
     data: {q: yql, format: 'json'}, 
     dataType: 'jsonp' 
    ).done(function(json) { 
     var forecasts = data.query.results.item.forecast; 
     var table = $('<table style="border: none">'); // prefer class/stylesheet 
     $.each(forecasts, function(forecast_i, forecast) { 
      table.append($('<tr>').append(
       $('<td class="weather-date">').text(forecast.day) 
      ).append(
       $('<td class="weather-icon">').css('background-position', forecast.code*-61 + 'px 0') 
      ).append(
       $('<td class="weather-min">').text(forecast.low+'°') 
      ).append(
       $('<td class="weather-max">').text(forecast.high+'°') 
      )); 
     }); 
     div.html(table); 
    }); 
}); 

筆記:

  • 使用jQuery的數據參數的自動轉換,以避免調用encodeURIComponent手動在JSON URL上。

  • 避免將字符串變量中的HTML內容粘在一起。它對HTML特殊字符失敗並可能引入安全問題(XSS)。要設置文本內容,請使用jQuery text()

  • 你可能根本不需要給元素一個id,如果你在這個JS變量中保存一個引用。

+0

謝謝!這是有效的(並且是一個寶貴的教訓) - 我只需做出2個改變:1.在ajax函數的末尾添加一個'}',並將'div.html(table)'切換爲'div.append(表)'以避免在裝載json數據時刪除名稱。 – sideroxylon