Isotope与JavaScript问题:新增元素后元素无法点击
解决图片点击放大失效的问题
作为过来人,我一眼就看出你遇到的是动态元素事件绑定和异步请求时序的典型问题,咱们一步步拆解解决:
1. 核心问题:新添加的图片没绑定点击事件
你一开始是给首次加载的.photo a绑定了点击事件,但通过Isotope插入的新元素根本没沾到这个事件。要是把事件代码塞进循环里,又会因为JavaScript闭包的特性,循环变量i最后会停在数组的最后一个索引,导致只有最后一张图片能触发点击。
解决方案:改用事件委托
把点击事件绑定在容器上,不管是旧元素还是新插入的元素,都能触发:
// 替换你原来的$photos.find('a').click(...)这段代码 $('#container').on('click', '.photo a', function() { var $this = $(this), $photo = $this.parents('.photo'); // 下面的逻辑直接复用你原来的就行 if ($photo.hasClass('large')) { $photo.removeClass('large'); $container.isotope('reLayout'); } else { if ($photo.hasClass('has-big-image')) { enlargeImage($photo); } else { $this.append($loadingIndicator); var $bigImage = $('<img>', { src: this.href }); $('<div>', { 'class': 'big-image' }) .append($bigImage) .appendTo($this) .imagesLoaded(function() { $loadingIndicator.remove() enlargeImage($photo); }); $photo.addClass('has-big-image'); } } return false; });
2. 第二个坑:异步请求的时序错误
你在setInterval里调用loadJSON后,直接把previous = current,但loadJSON是异步请求——这时候current可能还没更新成新的JSON数据,导致长度判断完全不准,甚至会覆盖掉正确数据。
解决方案:把逻辑放进请求回调里
// 先初始化previous为空数组,避免一开始length报错 var previous = []; setInterval(function() { loadJSON(function(response) { var newCurrent = JSON.parse(response); // 对比新旧数据长度,有变化才更新 if (previous.length !== newCurrent.length) { UpdateBody(previous.length, newCurrent); } // 等新数据拿到手,再更新previous previous = newCurrent; }); }, 5000); // 修改UpdateBody,直接用传入的新数据 function UpdateBody(startIndex, currentData) { var newElements = ""; for (let i = startIndex; i < currentData.length; i++) { newElements += '<div class="photo element-item">' + '<a href="' + currentData[i].image + '"><img class="small-image" src="' + currentData[i].image + '"/></a>' + '<a class="weight">' + currentData[i].weight + '</a></div>'; } var $newElems = $(newElements); $('#container').append($newElems).imagesLoaded(function() { $('#container').isotope('insert', $newElems); }); }
3. 清理多余的$(document).ready
你在UpdateBody的循环里嵌套了$(document).ready,这完全没必要,还会导致每次循环都把newElements重置为空,最后只插入最后一张图片——直接把这段删掉就行。
最后给你划几个新手必记的要点
- 动态添加的元素,一定要用事件委托绑定事件,不能直接绑在元素上
- 异步请求的逻辑必须在回调里处理,别在请求外面直接用返回值
- 循环里绑定事件要注意闭包坑,要么用
let(你已经用了),要么用事件委托(更省心)
内容的提问来源于stack exchange,提问作者AMayer
相关产品推荐
相关产品推荐

