单击标记时,Google Maps v3会打开最后一个infoWindow
我有一个共享的infoWindow
用于我的所有标记。 如果我使用jquery的$().each(function(){})
,它会很好用,但如果我将它更改为JavaScrips的native或while循环,它就不会按预期工作。
每当我点击一个标记时,它将打开最后一个填充标记的infoWindow
,而不是单击标记的infoWindow
。
这有效:
$(stores).each(function() { var storeId = $(this).attr('storeId'); var address = $(this).attr('rawAddress'); var city = $(this).attr('city'); var state = $(this).attr('state'); var zip = $(this).attr('zip'); var lat = $(this).attr('lat'); var lng = $(this).attr('lng'); var distance = $(this).attr('distance'); //create marker var point = new google.maps.LatLng(lat, lng); var marker = new google.maps.Marker({ position: point , map: InStorePickup.map , title: city + ' #' + storeId }); //create infowindow content var infoWindowContent = '' + '' + city + ' #' + storeId + ' (' + parseFloat(distance).toFixed(2) + 'mi)
' + address + '
' + city + ', ' + state + ' ' + zip + ''; google.maps.event.addListener(marker, 'click', function() { InStorePickup.openInfoWindow(marker, infoWindowContent); }); bounds.extend(point); });
但这不起作用:
for (var i = 0; i < 3; i++) { var store = stores[i]; var storeId = $(store).attr('storeId'); var address = $(store).attr('rawAddress'); var city = $(store).attr('city'); var state = $(store).attr('state'); var zip = $(store).attr('zip'); var lat = $(store).attr('lat'); var lng = $(store).attr('lng'); var distance = $(this).attr('distance'); //create marker var point = new google.maps.LatLng(lat, lng); var marker = new google.maps.Marker({ position: point , map: InStorePickup.map , title: city + ' #' + storeId }); //create infowindow content var infoWindowContent = '' + '' + city + ' #' + storeId + ' (' + parseFloat(distance).toFixed(2) + 'mi)
' + address + '
' + city + ', ' + state + ' ' + zip + ''; google.maps.event.addListener(marker, 'click', function() { InStorePickup.openInfoWindow(marker, infoWindowContent); }); bounds.extend(point); }
有什么想法吗?
你会在for
循环中遇到一个非常常见的闭包问题 。 顺便提一下, 我昨天就这个话题回答了类似的问题 ,你可能想看一下。
封闭在闭包中的变量共享相同的单个环境,因此在调用click
回调时,循环将运行其路线,并且infoWindowContent
变量将指向它分配给它的最后一个值。
解决这个问题的一种方法是使用函数工厂进行更多闭包:
function makeInfoWindowListener (pMarker, pContent) { return function() { InStorePickup.openInfoWindow(pMarker, pContent); }; } // ... for (var i = 0; i < 3; i++) { // ... var infoWindowContent = '' + city + '...'; google.maps.event.addListener( marker, 'click', makeInfoWindowListener(marker, infoWindowContent) ); }
如果您不熟悉闭包的工作方式,这可能是一个非常棘手的主题。 您可能有兴趣查看以下文章以获得简要介绍:
- Mozilla开发中心:使用闭包
更新:
jQuery示例工作的原因是因为传递给each()
方法的函数将每个迭代包含在其自己的作用域中。 在普通的JavaScript示例中,您几乎可以做同样的事情:
for (var i = 0; i < 3; i++) { // each iteration will now have its own scope (function () { var infoWindowContent = '' + city + '...'; google.maps.event.addListener(marker, 'click', function() { InStorePickup.openInfoWindow(marker, infoWindowContent); }); })(); }
第二次更新:
请注意,第一个示例也可以使用匿名函数重写如下:
for (var i = 0; i < 3; i++) { // ... var infoWindowContent = '' + city + '...'; google.maps.event.addListener(marker, 'click', (function (pMarker, pContent) { return function() { InStorePickup.openInfoWindow(pMarker, pContent); }; })(marker, infoWindowContent)); }