简体   繁体   English

侦听器事件始终以最后一个元素的信息触发

[英]Listener event always triggers with last element's info

I'm trying to make a map-based application, but I'm having bit of difficulty. 我正在尝试制作基于地图的应用程序,但遇到了一些困难。 The original code I had been working with added a separate InfoWindow for each marker, but I'd like to get it using a single InfoWindow for which I can set the content on the fly. 我一直在使用的原始代码为每个标记添加了一个单独的InfoWindow,但是我想使用单个InfoWindow来获取它,我可以为其动态设置内容。

However, I still seem to be a little fuzzy on how JavaScript behaves, because each time any marker is clicked the InfoWindow pops up over the last marker and the alert indicates the ID of the last entry in locations . 但是,对于JavaScript的行为,我似乎仍然有些模糊,因为每次单击任何标记时,InfoWindow都会在最后一个标记上方弹出,并且警报会指示locations最后一个条目的ID。

Short snippet, problem highlighted: 简短摘要,问题突出显示:

function plotLocations(my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
// ! -- trouble right here -- ! //
        google.maps.event.addListener(marker, 'click', function() {
            setPopInfo(pos, i);
        });
// ! -- ------------------ -- ! //
    }
}

function setPopInfo(pos, index) {
    pop_info.setPosition(pos);
    pop_info.open(map);
    window.alert(pos+"::"+index);
}

Most of the rest of my code: 我的其余大部分代码:

var map;
var mapBounds;
var locations;
var pop_info;

$(document).ready(init);

function init() {
    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
    pop_info = new google.maps.InfoWindow({
        content: "I'm not populated!",
        size: new google.maps.Size(100,25)
    });
    google.maps.event.addListener(map, 'bounds_changed', function() {
        queryLocations(map.getBounds());
    });

    prepareGeolocation();
    doGeolocation();
}

function queryLocations(bounds) {
    jQuery.ajax({
        url: 'http://mydomain.com/myapp/test2.php',
        data: bounds.toString(),
        dataType: 'json',
        success: addLocations
    });
}

function addLocations(new_locations) {
    document.getElementById('footer').innerHTML = new_locations;
    plotLocations(new_locations);
}

My reasoning for the single InfoWindow is that once a few hundred Markers and InfoWindows have been created the performance might take a nosedive. 我对单个InfoWindow的推理是,一旦创建了数百个Markers和InfoWindows,性能可能会下降。 Is what I'm trying to do feasible/advisable? 我想做的事可行/建议吗?

The problem occurs because you're defining your event listener callback function inside the loop. 发生问题是因为您正在循环内定义事件侦听器回调函数。 Closures refer to their context dynamically rather than binding to a copy of the data at the time of definition, so you have effectively created locations.length number of functions that are all bound to the same values of marker , pos and i , which are whatever they happened to be when the loop terminated. 闭包是动态引用其上下文的,而不是在定义时绑定到数据的副本,因此您已经有效地创建了locations.length个函数,它们全部绑定到markerposi的相同值,无论它们恰好是循环终止的时间。

To work round this, you could create a function that calls addListener outside the body of the loop, like so: 要解决此问题,您可以创建一个在循环主体外部调用addListener的函数,如下所示:

function plotLocations (my_locations) {
    locations = my_locations;
    for(var i=0; i<locations.length; i++) {
        var pos = new google.maps.LatLng(locations[i].loc_lat, locations[i].loc_lng);
        var icon = new google.maps.MarkerImage(
            "http://goo.gl/TQpwU",
            new google.maps.Size(20,32),
            new google.maps.Point(0,0),
            new google.maps.Point(0,32)
        );
        var marker = new google.maps.Marker({
            map: map,
            position: pos,
            animation: google.maps.Animation.DROP,
            icon: icon
        });
        bindEvent(marker, pos, i);
    }
}

function bindEvent (marker, pos, i) {
    google.maps.event.addListener(marker, 'click', function() {
        setPopInfo(pos, i);
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用循环删除事件侦听器仅删除最后一个元素的侦听器 - Removing event listener using loop removes only last element's listener Javascript侦听器在事件目标的子对象而非实际元素上触发 - Javascript listener triggers on child of the event target, not the actual element 事件侦听器仅适用于最后创建的元素 - Event listener only applying to last created element 将事件监听器保留在列表的最后一个元素上 - Keep event listener on last element of list 事件侦听器内的函数仅在其初始化时触发 - Function inside event listener triggers only on it's initialization 单击触发它创建的事件侦听器 - Click Triggers Event Listener That It Creates 动态事件监听器仅在最后创建的元素上起作用 - Dynamic Event Listener Working only on the Last Created Element 仅为 forEach 循环中的最后一个元素创建事件侦听器 - An event listener is only created for the last element in forEach loop 在 JavaScript 中引用另一个元素的事件侦听器中尚未创建的元素 - Referencing a yet to be created element in another element's event listener in JavaScript 如果div的子节点都具有特定的类名,如何创建触发事件的Javascript侦听器 - How to create a Javascript listener that triggers an event once a div's children all have a particular class name
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM