2009-01-29 77 views
1

我在我的页面上有一个多个菜单,它们全部使用相同的鼠标悬停和点击事件,因此我决定将它变成一个函数。然而,变量似乎总是被分配给悬停(函数,函数)函数的最后一个参数。jQuery和关闭

$(document).ready(function() { 
menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
    } 
} 
menuMouseOver({ parent: '#menu1', 
       active: 'menu1_active', 
       childSelect: ':gt(0)'}, 
      { parent: '#menu2', 
       active: 'menu2_active', 
       childSelect: ':gt(0)'}); 
}); 

为什么是最后的console.log将始终记录最后活跃而不是属于参数[I]。活跃的一个。 (在这个例子中,它始终记录下有效的的参数[1] .active) 我在做什么错了?

此外,真正的功能更复杂,但问题也出现在这个变体中。

回答

1

您的问题是悬停事件发生在执行方法的范围之外。因此,在悬停执行时,您的活动变量已经通过了整个集合并停留在最后一个元素的活动状态。所以你看到了这个问题,因为最后一个日志是一个事件,它超出了范围,另外两个在循环范围内。

试试这个:

 $(parent).children(childSelect) 
      .not('.'+active).each(function(i, e) { 
       console.log(active); 
       $(this).data("active", active); 
      }) 
      .hover(function() { 
       $(this).addClass($(this).data("active")); 
      }, function() { 
       $(this).removeClass($(this).data("active"))); 
      }); 

这将实际存储的DOM元素内的“活动”值,以便它可以在范围内进行访问。

+0

非常感谢。 – 2009-01-29 18:26:00

0

我绞尽脑汁,因为它是一个奇怪的问题,但我重构功能了一下,可能是有用的(呵呵,有人要聪明得多与此同时回答):

$("#menu1,#menu2").each(function(){ 
    var id = $(this).attr("id"); 
    $(">li",this).not("."+id+"_active,:eq(0)").hover(function(){ 
     $(this).addClass(id+"_active"); 
    },function(){ 
     $(this).removeClass(id+"_active"); 
    }); 
}); 
4

JavaScript没有块范围,所以你在for循环中声明的那些变量在每次迭代时改变它们的值,并且所有这些函数都引用相同的变量。诀窍是在for循环中创建一个新的函数作用域,以便在迭代过程中声明的变量被绑定。

您可以通过在循环中执行一个匿名函数实现这一点:

menuMouseOver = function() { 
    for(i=0, u=arguments.length; i<u; i++){ 
     (function(){ // anonymous function to create new scope 
     var parent = arguments[i].parent; 
     var active = arguments[i].active; 
     var childSelect = arguments[i].childSelect; 
     console.log(active); //logs the correct active 
      $(parent).children(childSelect) 
       .not('.'+active).each(function(i, e) {console.log(active);}) 
//The above console.log logs the correct active 
        .hover(function() { 
          console.log(active); //this one always logs menu2_active 
          $(this).addClass(active); 
         }, function() { 
          $(this).removeClass(active); 
         }); 
     })(); // execute the anonymous function 
    } 
} 

你以前有它的方式,大家的功能关闭了同一个变量的引用,所以用什么都的最后一个值是,而不是功能创建时的价值。使用函数作用域将使其表现得如你所愿。