Google Maps标记数组addListener点击事件异常问题求助
问题解决:Google Maps标记点击事件始终触发最后一个标记的事件
问题核心原因
这是循环中闭包作用域导致的经典问题:你在循环里定义的点击事件函数,捕获的是变量i的引用而非每次循环时i的具体值。当循环完全结束后,i已经变成了info.length,所以所有标记的点击事件触发时,都会调用这个最终值。
三种可行解决方案
1. 使用ES6 let关键字(最简方案)
把循环变量i改成let声明,let会在每次循环迭代时创建独立的变量绑定,确保每个事件函数捕获当前循环的i值:
for (let i = 0; i < info.length; i++) { toilet = info[i]; map_number = toilet.map_number; if (typeof marker_list[map_number][toilet.id] === "undefined") { unique_id = map_number + "_" + toilet.id; toilet_lat = parseFloat(toilet.lat); toilet_lng = parseFloat(toilet.lng); marker_x = parseFloat(toilet.marker_anchor_x); marker_y = parseFloat(toilet.marker_anchor_y); label_x = parseFloat(toilet.label_anchor_x); label_y = parseFloat(toilet.label_anchor_y); marker_anchor = new google.maps.Point(marker_x, marker_y); label_anchor = new google.maps.Point(label_x, label_y); marker[i] = new google.maps.Marker({ position: { lat: toilet_lat, lng: toilet_lng }, map: map, icon: { path: toilet.marker_path, anchor: marker_anchor, labelOrigin: label_anchor, fillColor: toilet.marker_colour, fillOpacity: 1, strokeWeight: 2, strokeColor: 'black' }, opacity: toilet.marker_opacity, draggable: toilet.marker_draggable }); marker[i].addListener('click', function() { alert(i); }); } marker_list[map_number][toilet.id] = marker[i]; }
2. 立即执行函数(IIFE)兼容ES5环境
如果需要兼容旧浏览器,用立即执行函数把当前i值封装到独立作用域:
for (i = 0; i < info.length; i++) { toilet = info[i]; map_number = toilet.map_number; if (typeof marker_list[map_number][toilet.id] === "undefined") { // 省略标记创建代码... marker[i] = new google.maps.Marker({/* 配置参数 */}); // 用IIFE捕获当前循环的i值 (function(currentIndex) { marker[currentIndex].addListener('click', function() { alert(currentIndex); }); })(i); } marker_list[map_number][toilet.id] = marker[i]; }
3. 给标记绑定自定义属性
直接把索引值存到Marker对象上,点击时通过this访问:
for (i = 0; i < info.length; i++) { toilet = info[i]; map_number = toilet.map_number; if (typeof marker_list[map_number][toilet.id] === "undefined") { // 省略标记创建代码... marker[i] = new google.maps.Marker({/* 配置参数 */}); marker[i].index = i; // 添加自定义属性存储当前索引 marker[i].addListener('click', function() { alert(this.index); }); } marker_list[map_number][toilet.id] = marker[i]; }
额外优化提示
- 原代码中
marker_list[map_number][toilet.id] = new Array();后又赋值为marker是冗余操作,直接赋值单个标记marker[i]更合理。 - 变量
toilet、map_number等建议用let/var声明,避免全局变量污染。
内容的提问来源于stack exchange,提问作者Felicity Penfold
相关产品推荐
相关产品推荐

