HTML5 Geolocation信息窗口显示重复用户名问题求助
解决地图标记点击后信息窗口显示同一用户名的问题
嗨,我完全懂你遇到的困扰!这是JavaScript循环里非常常见的闭包陷阱,咱们先搞清楚原因,再一步步修复~
问题根源
你在for循环里用var声明了key变量,而var是函数级作用域的——当循环结束后,所有的点击事件回调函数引用的都是同一个key变量,它最后指向的是循环里的最后一个用户,所以不管点哪个标记,都会显示最后那个用户名。另外你原代码里还有两个小语法错误:
google.maps.InfoWindow的构造函数需要传一个配置对象(比如包含content属性),不能直接传用户名- 事件绑定里的变量名和括号有拼写/语法问题
解决方案
这里给你两种靠谱的解决方法,选适合你的就行:
方法1:用ES6的let声明循环变量(推荐)
let是块级作用域,每次循环迭代都会创建一个新的key变量,这样每个点击回调都会绑定当前迭代的用户数据:
function loadMarkers(data) { // 把var改成let,创建块级作用域 for(let key in data) { var user = data[key]; xmartlabschat.addUser(user); markers[key] = getMarker(user.lat, user.lng, user.name); // 正确创建InfoWindow,传入content配置 var infoWindow = new google.maps.InfoWindow({ content: user.name }); // 绑定点击事件,修正语法问题 markers[key].addListener('click', function(){ infoWindow.open(map, markers[key]); }); } }
方法2:用立即执行函数(IIFE)创建独立作用域(兼容旧环境)
如果你的项目环境不支持ES6,可以用立即执行函数把每次循环的用户和标记封装成独立作用域:
function loadMarkers(data) { for(var key in data) { var user = data[key]; xmartlabschat.addUser(user); markers[key] = getMarker(user.lat, user.lng, user.name); // 用IIFE捕获当前迭代的user和marker (function(currentUser, currentMarker) { var infoWindow = new google.maps.InfoWindow({ content: currentUser.name }); currentMarker.addListener('click', function(){ infoWindow.open(map, currentMarker); }); })(user, markers[key]); } }
额外优化提示
如果想让体验更好,还可以在打开新的信息窗口前关闭之前的,避免多个窗口同时显示:
// 在循环外声明一个全局的infoWindow变量 let activeInfoWindow = null; // 点击事件里修改: markers[key].addListener('click', function(){ if (activeInfoWindow) { activeInfoWindow.close(); } activeInfoWindow = infoWindow; infoWindow.open(map, markers[key]); });
这样修改后,每个标记点击都会显示对应的用户名啦~
内容的提问来源于stack exchange,提问作者Jason Steve
相关产品推荐
相关产品推荐

