jQuery hover事件在for循环中仅首个元素生效问题求助
问题:循环生成元素后hover事件仅对首个元素生效
通过for循环创建两个玩家相关的div元素,实现鼠标悬停时改变对应统计div的高度,但hover事件仅对第一个生成的元素生效,其他基于ID的jQuery操作均正常。相关代码如下:
var result =[ 2, "name:Tom;bc:67;lp:77;fn:37;ic:65;ag:45;sp:56;st:54;pc:66", "name:Thomas;bc:70;lp:44;fn:70;ic:44;ag:60;sp:70;st:30;pc:30" ]; for (var a = 1; a < result[0] + 1; a++){ var players = result[a].split(";"); var playername = players[0].split(":"); var element = document.createElement("div"); var elementc = document.createElement("div"); var elements = document.createElement("div"); for (var s = 1; s < 8; s++){ var ps = document.createElement("p"); ps.innerHTML = players[s] + " "; elements.appendChild(ps); } element.id = playername[1]; elementc.id = playername[1] + "id"; elements.id = playername[1] + "stats"; elementc.appendChild(element); document.getElementById('manage').appendChild(elementc); document.getElementById('manage').appendChild(elements); document.getElementById(playername[1] + "id").style.position = "Relative"; document.getElementById(playername[1] + "id").style.position = "Relative"; document.getElementById(playername[1] + "id").style.width = "87vw"; document.getElementById(playername[1] + "id").style.margin = "0.5vw"; document.getElementById(playername[1] + "id").style.height = "10vw"; document.getElementById(playername[1] + "id").style.border = "1vw solid cyan"; document.getElementById(playername[1]).style.position = "Relative"; document.getElementById(playername[1]).style.cssFloat = "left"; document.getElementById(playername[1]).style.width = "10vw"; document.getElementById(playername[1]).style.height = "10vw"; document.getElementById(playername[1]).style.backgroundImage = "url(Players/" + playername[1] + ".jpg"; document.getElementById(playername[1]).style.backgroundSize = "cover"; document.getElementById(playername[1] + "stats").style.position = "Relative"; document.getElementById(playername[1] + "stats").style.backgroundColor = "lightgrey"; document.getElementById(playername[1] + "stats").style.overflowY = "scroll"; document.getElementById(playername[1] + "stats").style.width = "87vw"; document.getElementById(playername[1] + "stats").style.height = "20"; $("#" + playername[1] + "stats") .children().css("background", "linear-gradient(to right,#0D7377 50%, #ffffff 50%)"); $("#" + playername[1] + "stats") .children().css("width", "fit-content"); $("#" + playername[1] + "stats") .children().css("float", "left"); $("#" + playername[1] + "stats") .children().css("margin", "2vw"); $("#manage").children().css("margin-top", "30vw"); //The hover here $("#" + playername[1] + "id").hover( function(){ $("#" + playername[1] + "stats").animate({'height': '20vw'}, 'slow'); }, function(){ $("#" + playername[1] + "stats").animate({'height': '0vw'}, 'slow'); } ); }
问题原因
核心问题是**var声明的变量作用域特性和闭包的延迟绑定**:
- 用
var声明的playername属于函数级作用域,整个循环中只有一个变量实例。 - hover事件的回调函数是闭包,不会立即执行,当循环结束后,所有回调引用的
playername[1]都是循环最后一次的取值(即Thomas)。 - 因此无论悬停哪个
xxxid元素,最终都会操作Thomasstats这个div,导致视觉上只有第一个元素的hover“生效”(实际是错误触发了最后一个元素的统计框)。
解决方法
方案1:用let替代var声明变量
let具有块级作用域,每次循环会创建新的变量实例,回调函数会绑定当前循环的playername值:
// 修改循环变量和playername的声明方式 for (let a = 1; a < result[0] + 1; a++){ let players = result[a].split(";"); let playername = players[0].split(":"); // 剩余代码保持不变 }
方案2:利用闭包捕获当前变量值
通过立即执行函数(IIFE)创建闭包,保存当前循环的playername值:
// 替换原hover绑定代码 (function(currentName) { $("#" + currentName + "id").hover( function(){ $("#" + currentName + "stats").animate({'height': '20vw'}, 'slow'); }, function(){ $("#" + currentName + "stats").animate({'height': '0vw'}, 'slow'); } ); })(playername[1]);
方案3:通过DOM结构关联目标元素(推荐)
利用DOM元素的相邻关系,用jQuery的next()方法直接获取当前xxxid元素后的统计div,无需依赖变量:
// 替换原hover绑定代码 $("#" + playername[1] + "id").hover( function(){ $(this).next().animate({'height': '20vw'}, 'slow'); }, function(){ $(this).next().animate({'height': '0vw'}, 'slow'); } );
额外代码修复
- 初始统计div高度设置错误:
document.getElementById(playername[1] + "stats").style.height = "20";改为"0vw",确保初始状态隐藏。 - 背景图片URL缺少闭合括号:
backgroundImage = "url(Players/" + playername[1] + ".jpg"改为"url(Players/" + playername[1] + ".jpg)"。
内容的提问来源于stack exchange,提问作者Error 2.0
相关产品推荐
相关产品推荐

