单击标记时,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)); }