我正在编写一个简单的天气应用程序并且遇到了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>');
}
});
}
});
据Firebug所知,第一部分可行 - 正在检索正确的天气数据,并在父div中创建新的div。正确的位置名称也会附加到每个新div。它倒下是将天气数据附加到每个div。在第二个(最后一个)附加语句中识别子div的正确方法是什么,以便每个div有一次天气数据解析循环的迭代?感谢。
答案 0 :(得分:1)
for (j = 0; j<z.length; j++) {
$.getJSON(..., function (data) {
$('#c' + j + '').append(...
循环执行z.length
次,启动z.length
个AJAX请求,并在j
等于z.length
终止循环时完成。
然后,很久以后(因为AJAX中的'A'意味着'异步')请求完成并且每个回调函数都被调用。他们使用j
来选择要将结果附加到哪个div。但j
仍然是z.length
,因为它在循环结束时又回来了。创建一个带变量闭包的函数并不意味着从创建函数的那一点开始记住变量的值;每个函数都引用相同的j
。
(实际上你根本没有闭包,因为你的循环变量j
和i
没有被声明为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自动转换数据参数,以避免必须在JSON URL上手动调用encodeURIComponent
。
避免将字符串变量中的HTML内容粘在一起。它不适用于HTML特殊字符,可能会引入安全问题(XSS)。要设置文本内容,请使用jQuery text()
。
如果你在这样的JS变量中保留对它的引用,你可能根本不需要给它一个id
。