jQuery:使用闭包修复点击for循环中的函数绑定
我被困在这里,任何提示都会很好。
我有一个Objects对象[]和一个divnames []数组。 我的对象上有play()和stop()等函数。 对象及其function在多种情况下进行了测试,它们正在运行。 现在我尝试迭代divnames []并将适当对象[]的动作分配给mouseover,mouseout和click。
有一个闭包问题,我修复了一个解决方案,我在StackOverflow上的另一个线程中找到了。 这样可行。 但剩下的问题是鼠标hover等操作不会分配给稍后加载的div。 他们正在处理从一开始就在页面上的对象。
这是我有的:
$(function(){ for (var i=0, len=divnames.length; i<len; i++) { if(divnames[i]){ (function( ) { // anonymous function to fix closures var index = i; // also needed to fix closures $('#'+divnames[index]).on("click", function() { objects[index].play(); loadContent(divnames[index]+".php"); }); })( ); // direct function execution to fix closures } } });
如上所述,闭包问题由两个注释行修复,将它们留下只会应用for循环的最后一次执行。 就像现在一样,这是有效的。
但是无效的是,click函数也应该应用于匹配选择器的div,但尚未加载。
但是,如果具有相同function的代码没有在没有闭包修复的情况下在for循环内迭代,那确实有效,因为如果我理解正确的话,那就是预期的.on()行为。
那么我如何才能获得所需的function呢?
感谢您提前的时间。
– – 编辑 – –
所需的其他信息:
var divnames = []; divnames[0] = "home"; divnames[1] = "about"; divnames[2] = "projects"; function SpriteAnim (options) { var timerId = 0; var i = 0; this.status = 0; this.init = function () { var element = document.getElementById(options.elementId); element.style.width = options.width + "px"; element.style.height = options.height + "px"; element.style.backgroundRepeat = "no-repeat"; element.style.backgroundImage = "url(" + options.sprite + ")"; }; this.showFrame = function (which) { if (which < options.frames) { i = which; element = document.getElementById(options.elementId); element.style.backgroundPosition = "0px -" + which * options.height + "px"; } }; this.play = function () { this.status = 2; timerId = setInterval(function () { if (i < (options.frames - 1)) { i++; element = document.getElementById(options.elementId); element.style.backgroundPosition = "0px -" + i * options.height + "px"; } else { clearInterval(timerId); this.status = 1; } }, 100); }; }
正如您可能已经猜到的那样,objects []数组在对象[0],对象[1],对象[2]中包含3个SpriteAnim对象。
objects[0] = new SpriteAnim({ width: 7, height: 7, frames: 8, sprite: "myanim1.png", elementId: "anim0" }); objects[1] = new SpriteAnim({ width: 7, height: 7, frames: 8, sprite: "myanim1.png", elementId: "anim1" }); objects[2] = new SpriteAnim({ width: 7, height: 7, frames: 8, sprite: "myanim2.png", elementId: "anim2" });
这是因为索引是在绑定语句之外声明的。 当点击进入该调用时,它不知道[index]是什么对象。
如果你想保持相同的结构,重做你的function,如下所示:
$(function(){ for (var i=0, len=divnames.length; i
实际上,你应该这样做:
$(document).on('click','div[name=home],div[name=projects],div[name=about]', function(){ var name = $(this).attr('name'); switch (name){ case 'home': objects[0].play(); break; // and so on } loadContent(name + '.php'); });
编辑:
当你点击你的div时,这就是它将要注意的全部内容:
objects[index].play(); loadContent(divnames[index]+".php");
您需要使用事件委派,并在父元素而不是元素本身上侦听这些事件。 这样,如果稍后添加新元素,则无需重新绑定它们。
$("#buttons").on("click", ".button", function(){ console.log("You clicked on a .button element."); });
在这种情况下,我们绑定到#buttons
上的click事件,但仅当调用元素与选择器.button
匹配时。 你的标记将是这样的:
当任何.button
元素发生单击,并且#buttons
父元素出现气泡时,它将被拦截并触发处理程序。