JavaScript addEventListener异常:mouseenter事件始终返回数组最后一项
循环绑定mouseenter事件时获取到的总是数组最后一项的问题
我在使用JavaScript的addEventListener绑定mouseenter事件时遇到问题。原本计划实现当产品图片数组长度大于1时,鼠标悬停在预览图上切换显示其他图片,但目前在循环内绑定的mouseenter事件触发时,始终返回数组的最后一项,而非当前选中项。
原代码
var product_type = ""; for(let i = 0; i < this.products_list.length; i++){ var row = this.products_list[i], self = this; if(row.product_type != product_type){ product_type = row.product_type; var sub_title = document.createElement("h2"), separator = document.createElement("hr"), display_list = document.createElement("ul"); sub_title.id = product_type; sub_title.innerHTML = localeString.get(product_type); display_list.id = product_type+"-list"; this.catalog.appendChild(sub_title); this.catalog.appendChild(separator); this.catalog.appendChild(display_list); } var product = document.createElement("li"), preview = document.createElement("img"), container = document.createElement("div"); var array_images = row.product_images.split(","); preview.src = this.assets+product_type+"/"+array_images[0]+".jpg"; preview.alt = product_type+"#"+row.product_id; container.appendChild(preview); product.appendChild(container); preview.addEventListener("mouseenter", event => { console.log(array_images); // 这里总是输出数组的最后一项,而非当前选中项 }); display_list.appendChild(product); }
问题原因
你用var声明了array_images,var是函数作用域,循环里每次赋值都会覆盖同一个变量。事件回调是异步触发的,等回调执行时,循环已经跑完,array_images早已经被最后一次循环的赋值覆盖,所以所有回调都指向最后那个数组。
解决方法
方法1:把var array_images改成let
利用let的块级作用域特性,每次循环都会创建一个独立的array_images变量,回调里引用的就是当前循环对应的数组:
// 把var改成let let array_images = row.product_images.split(",");
方法2:用立即执行函数隔离作用域
把事件绑定逻辑包裹在立即执行函数里,将当前的array_images作为参数传入,形成独立作用域:
var array_images = row.product_images.split(","); // ... 其他代码 (function(currentImages) { preview.addEventListener("mouseenter", event => { console.log(currentImages); }); })(array_images);
方法3:把数组存在元素自定义属性里
将array_images转成字符串存在预览图的dataset属性中,触发事件时再解析出来:
var array_images = row.product_images.split(","); // 存自定义属性时转成JSON字符串 preview.dataset.productImages = JSON.stringify(array_images); preview.addEventListener("mouseenter", event => { // 触发时解析字符串得到原数组 const currentImages = JSON.parse(event.target.dataset.productImages); console.log(currentImages); });
内容的提问来源于stack exchange,提问作者W.DavidC
相关产品推荐
相关产品推荐

