js循环动态绑定click事件问题

lee_ttxs 2018-09-07 11:05:43
// //方法一:循环调用窗口,失败,why?
for (var i = 0; i < lists.length; i++) {

point[i] = new window.BMap.Point(lists[i]['ownerlng'],lists[i]['ownerlat']);//循环生成新的地图点
marker[i] = new window.BMap.Marker(point[i]); //按照地图点坐标生成标记
map.addOverlay(marker[i]); // 将标注添加到地图中
marker[i].setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
var label = new window.BMap.Label(lists[i]['basename'], { offset: new window.BMap.Size(20, -10),enableMassClear: false });
label.setStyle({ color : "white", fontSize : "12px" })
marker[i].setLabel(label);


info[i] = new window.BMap.InfoWindow("<p style=’font-size:12px;lineheight:1.8em;’>基地:" + lists[i]['basename'] + "</br>编号:" + lists[i]['baseno'] + "</br> 地址:" + lists[i]['ownerprovince'] + lists[i]['ownercity'] + lists[i]['ownerzone'] + lists[i]['ownerpositon'] + "</br></p>"); // 创建信息窗口对象

marker[i].addEventListener("mouseover", function () {
this.openInfoWindow((window.BMap.InfoWindow)(info[i]));
});



}

//方法二:循环调用窗口,成功,why?
for (var i = 0; i < lists.length; i++) {

point[i] = new window.BMap.Point(lists[i]['ownerlng'],lists[i]['ownerlat']);//循环生成新的地图点
marker[i] = new window.BMap.Marker(point[i]); //按照地图点坐标生成标记
map.addOverlay(marker[i]); // 将标注添加到地图中
marker[i].setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
var label = new window.BMap.Label(lists[i]['basename'], { offset: new window.BMap.Size(20, -10),enableMassClear: false });
label.setStyle({ color : "white", fontSize : "12px" })
marker[i].setLabel(label);


info[i] = "<p style=’font-size:12px;lineheight:1.8em;’>基地:" + lists[i]['basename'] + "</br>编号:" + lists[i]['baseno'] + "</br> 地址:" + lists[i]['ownerprovince'] + lists[i]['ownercity'] + lists[i]['ownerzone'] + lists[i]['ownerpositon'] + "</br></p>"; // 创建信息窗口对象

addInfo(marker[i],info[i]);
}

function addInfo(marker,txt){
var infoWindow = new BMap.InfoWindow(txt);
marker.addEventListener("mouseover", function(){this.openInfoWindow(infoWindow);});
}
...全文
841 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
lee_ttxs 2020-01-22
  • 打赏
  • 举报
回复
引用 10 楼 噢耶~ 的回复:
大佬,解决了吗?能不能给我参考一下,这个回复有点看不懂
邮箱:2053759601@qq.com
谢谢


当时解决了,你看上面的回复吧。程序早就不知道哪里去了
lee_ttxs 2018-09-10
  • 打赏
  • 举报
回复
引用 7 楼 qq_41114603 的回复:
[quote=引用 5 楼 lee_ttxs 的回复:]
[quote=引用 1 楼 qq_41114603 的回复:]
看下这个,

let arr = [1,2,3,4,5];
for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮"+i+"</button>");
btn.on("click",function(){
alert(i)
})
$("body").append(btn) //所有点击都是 alert ( 5 )
}

for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮二"+i+"</button>");
(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);
$("body").append(btn) // alert ( 0 ) alert ( 1 ) alert ( 2 ) alert ( 3 ) alert ( 4 )
}

这就是形参和实参的含义,
方法一在mouseover函数中直接使用 变量 i ,所以每次都是循环后的值,也就是每一个时间取的都是同一个值;
方法二 在mouseover函数中使用的时形参 i , 形参在接收完实参的数据之后,实参再发生变化不会影响到形参



(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);


这么写的目的是什么,什么情况下使用闭包恰当?[/quote]
事件里面的alert(i)相当于alert(window.i);但是for循环后i已经是循环后的值了;所以在绑定事件的时候需要把当时的i记录下来,上面的代码是通过形参去接收当时的i;形参在自执行函数结束后被事件函数引用形成闭包,就会一直存在;

闭包的作用:1、保存这个变量,不被回收;2、只有形参闭包的函数是唯一访问该变量的入口,不能被其他函数访问

全局变量:全局都能访问,window存在就不会被回收; 局部变量:局部访问,代码执行完就被回收;闭包:局部访问,引用关系存在就不会被回收;

[/quote]

讲的明白透彻,非常感谢!
lee_ttxs 2018-09-10
  • 打赏
  • 举报
回复
引用 6 楼 onepersons 的回复:
你说的“失败”是指鼠标滑过的时候显示的内容都是一样的吗?
当触发 “mouseover”事件之后,
方法一会执行

this.openInfoWindow((window.BMap.InfoWindow)(info[i]))

i 的值都是for循环最后一次自增的值。

方法二会执行

addInfo(marker[i],info[i]);

的时候会创建新的作用域,当执行到

marker.addEventListener("mouseover", function(){this.openInfoWindow(infoWindow);});

时,由于事件回调函数中引用了这个作用域中的“infoWindow”变量,导致addInfo函数在执行结束后,其作用域不会被回收 ,

this.openInfoWindow(infoWindow)

是引用了不同作用域中的 infoWindow 变量。


非常感谢!
風灬雲 2018-09-09
  • 打赏
  • 举报
回复
引用 5 楼 lee_ttxs 的回复:
[quote=引用 1 楼 qq_41114603 的回复:]
看下这个,

let arr = [1,2,3,4,5];
for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮"+i+"</button>");
btn.on("click",function(){
alert(i)
})
$("body").append(btn) //所有点击都是 alert ( 5 )
}

for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮二"+i+"</button>");
(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);
$("body").append(btn) // alert ( 0 ) alert ( 1 ) alert ( 2 ) alert ( 3 ) alert ( 4 )
}

这就是形参和实参的含义,
方法一在mouseover函数中直接使用 变量 i ,所以每次都是循环后的值,也就是每一个时间取的都是同一个值;
方法二 在mouseover函数中使用的时形参 i , 形参在接收完实参的数据之后,实参再发生变化不会影响到形参



(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);


这么写的目的是什么,什么情况下使用闭包恰当?[/quote]
事件里面的alert(i)相当于alert(window.i);但是for循环后i已经是循环后的值了;所以在绑定事件的时候需要把当时的i记录下来,上面的代码是通过形参去接收当时的i;形参在自执行函数结束后被事件函数引用形成闭包,就会一直存在;

闭包的作用:1、保存这个变量,不被回收;2、只有形参闭包的函数是唯一访问该变量的入口,不能被其他函数访问

全局变量:全局都能访问,window存在就不会被回收; 局部变量:局部访问,代码执行完就被回收;闭包:局部访问,引用关系存在就不会被回收;

onepersons 2018-09-09
  • 打赏
  • 举报
回复
你说的“失败”是指鼠标滑过的时候显示的内容都是一样的吗?
当触发 “mouseover”事件之后,
方法一会执行

this.openInfoWindow((window.BMap.InfoWindow)(info[i]))

i 的值都是for循环最后一次自增的值。

方法二会执行

addInfo(marker[i],info[i]);

的时候会创建新的作用域,当执行到

marker.addEventListener("mouseover", function(){this.openInfoWindow(infoWindow);});

时,由于事件回调函数中引用了这个作用域中的“infoWindow”变量,导致addInfo函数在执行结束后,其作用域不会被回收 ,

this.openInfoWindow(infoWindow)

是引用了不同作用域中的 infoWindow 变量。
lee_ttxs 2018-09-08
  • 打赏
  • 举报
回复
引用 1 楼 qq_41114603 的回复:
看下这个,

let arr = [1,2,3,4,5];
for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮"+i+"</button>");
btn.on("click",function(){
alert(i)
})
$("body").append(btn) //所有点击都是 alert ( 5 )
}

for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮二"+i+"</button>");
(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);
$("body").append(btn) // alert ( 0 ) alert ( 1 ) alert ( 2 ) alert ( 3 ) alert ( 4 )
}

这就是形参和实参的含义,
方法一在mouseover函数中直接使用 变量 i ,所以每次都是循环后的值,也就是每一个时间取的都是同一个值;
方法二 在mouseover函数中使用的时形参 i , 形参在接收完实参的数据之后,实参再发生变化不会影响到形参



(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);


这么写的目的是什么,什么情况下使用闭包恰当?
lee_ttxs 2018-09-08
  • 打赏
  • 举报
回复
引用 2 楼 u013116426 的回复:
应该是闭包问题吧,代码看着眼睛疼


哪里的闭包呢,不太明白,请教
lee_ttxs 2018-09-08
  • 打赏
  • 举报
回复



// //方法一:循环调用窗口,失败,why?
for (var i = 0; i < lists.length; i++) {

point[i] = new window.BMap.Point(lists[i]['ownerlng'],lists[i]['ownerlat']);//循环生成新的地图点
marker[i] = new window.BMap.Marker(point[i]); //按照地图点坐标生成标记
map.addOverlay(marker[i]); // 将标注添加到地图中
marker[i].setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
var label = new window.BMap.Label(lists[i]['basename'], { offset: new window.BMap.Size(20, -10),enableMassClear: false });
label.setStyle({ color : "white", fontSize : "12px" })
marker[i].setLabel(label);


info[i] = new window.BMap.InfoWindow("<p style=’font-size:12px;lineheight:1.8em;’>基地:" + lists[i]['basename'] + "</br>编号:" + lists[i]['baseno'] + "</br> 地址:" + lists[i]['ownerprovince'] + lists[i]['ownercity'] + lists[i]['ownerzone'] + lists[i]['ownerpositon'] + "</br></p>"); // 创建信息窗口对象

marker[i].addEventListener("mouseover", function () {
this.openInfoWindow((window.BMap.InfoWindow)(info[i]));
});
}

//方法二:循环调用窗口,成功,why?
for (var i = 0; i < lists.length; i++) {

point[i] = new window.BMap.Point(lists[i]['ownerlng'],lists[i]['ownerlat']);//循环生成新的地图点
marker[i] = new window.BMap.Marker(point[i]); //按照地图点坐标生成标记
map.addOverlay(marker[i]); // 将标注添加到地图中
marker[i].setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
var label = new window.BMap.Label(lists[i]['basename'], { offset: new window.BMap.Size(20, -10),enableMassClear: false });
label.setStyle({ color : "white", fontSize : "12px" })
marker[i].setLabel(label);


info[i] = "<p style=’font-size:12px;lineheight:1.8em;’>基地:" + lists[i]['basename'] + "</br>编号:" + lists[i]['baseno'] + "</br> 地址:" + lists[i]['ownerprovince'] + lists[i]['ownercity'] + lists[i]['ownerzone'] + lists[i]['ownerpositon'] + "</br></p>"; // 创建信息窗口对象

addInfo(marker[i],info[i]);
}

function addInfo(marker,txt){
var infoWindow = new BMap.InfoWindow(txt);
marker.addEventListener("mouseover", function(){this.openInfoWindow(infoWindow);});
}

___紫菜 2018-09-07
  • 打赏
  • 举报
回复
应该是闭包问题吧,代码看着眼睛疼
風灬雲 2018-09-07
  • 打赏
  • 举报
回复
看下这个,

let arr = [1,2,3,4,5];
for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮"+i+"</button>");
btn.on("click",function(){
alert(i)
})
$("body").append(btn) //所有点击都是 alert ( 5 )
}

for(var i=0,len=arr.length; i<len; i++){
let btn=$("<button>"+"按钮二"+i+"</button>");
(function(btn,i){
btn.on("click",function(){
alert(i)
});
})(btn,i);
$("body").append(btn) // alert ( 0 ) alert ( 1 ) alert ( 2 ) alert ( 3 ) alert ( 4 )
}

这就是形参和实参的含义,
方法一在mouseover函数中直接使用 变量 i ,所以每次都是循环后的值,也就是每一个时间取的都是同一个值;
方法二 在mouseover函数中使用的时形参 i , 形参在接收完实参的数据之后,实参再发生变化不会影响到形参

87,907

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧