setTimeout()和设置参数
我有一些看起来像这样的jQuery代码:
$('.mainNav2 > li').mouseleave(function(){ var someNum = Math.random(); $(this).attr('id', someNum); var t = setTimeout("HideMenu(someNum)", 200); $('li.clicked').mouseenter(function() { clearTimeout(t); }); }); function HideMenu(id) { $('#'+id).removeClass('clicked'); }
它的目的是在鼠标离开时隐藏一个巨大的菜单,但也考虑到意外的鼠标离开,使用300毫秒setTimeout。 如果用户在300毫秒内将鼠标指针返回到li,则不会隐藏菜单,因为调用了clearTimout(t)。
问题是当用户意图捕鼠时,没有调用setTimout中的函数。 根据这个页面: http : //www.w3schools.com/js/js_timing.asp我的语法是正确的,但我只能从setTimeout中调用HideMenu函数,如果我这样写:
var t = setTimeout(HideMenu, 300);
为什么它不能像写入一样工作,我可以将变量作为参数传递给函数?
虽然明确正确的答案是实现这一目标的一种方法……我不相信这是正确的。
请参阅随附的JS小提琴: http : //jsfiddle.net/PWHw3/
我们在这里做的主要是:
setTimeout(function, timeout, param);
例:
var test = function(a){ var b = (a) ? a : "fail"; alert(b); }; setTimeout(test, 500, "works");
这对我有用,并且消除了通过两个function的需要。
为了使它工作,并且不使用令人讨厌的eval版本的setTimeout更改:
var t = setTimeout("HideMenu(someNum)", 200);
对此:
var t = setTimeout(function(s) { return function() { HideMenu(s) } }(someNum), 200);
这样就可以将someNum
的值传递给setTimeout
范围内的变量s
。
setTimeout
接受函数和毫秒延迟。 该函数可以是函数引用,也可以是在超时触发时进行评估的字符串。 您当前的序列如下所示:
-
mouseleavefunction
- 为变量
someNum
赋值。 someNum的范围限定为当前函数 - 设置一个计时器,在200ms后评估字符串
"HideNum(someNum)"
。 - 结束function,保留function范围
- 为变量
-
200ms通过
- 评估
"HideNum(someNum)"
。 它应该抛出一个exception,因为变量someNum是未定义的。 这就是为什么不调用HideNum的原因 – 检查控制台中的错误。
你想要的是一个函数引用,它将使你的someNum保持在范围内(通过闭包 – 你可能想要阅读它)。
setTimeout(function() { HideNum(someNum); }, 200);
您会发现Mozilla文档是JavaScript的更好参考。 这是window.setTimeout文档。
你想要做的是创建一个匿名函数并在setTimeout调用中调用它。
setTimeout(function() { HideMenu(someNum) }, 200);
但是,如果我正确理解你想要做什么,你就不必费心去设置id和所有这些东西。 这样的事情应该这样做:
$('.mainNav2 > li').mouseleave(function() { var $this = $(this); var t = setTimeout(function() { $this.removeClass('clicked'); }, 200); $('li.clicked').mouseenter(function() { clearTimeout(t); }); });
还有更多方法可以做到这一点。
1.使用匿名function(推荐)
setTimeout(function() { hideMenu('someNum'); }, 200);
2. setTimeout
和setInterval
具有隐藏function:您可以在超时后指定参数。
setTimeout(hideMenu, 200, params);
既然你已经在使用jQuery了,你不应该创建一个单独的函数,而是扩展jQuery的原型,如下所示:
jQuery.fn.hideMenu = function() { this.removeClass('clicked'); return this; };
用法:
$('#num').hideMenu();
请注意,当您扩展其原型时,您不需要将其传递给jQuery,因为它已经传递给jQuery。 并return this;
要求保持链接的能力。
如果你选择这种方式,你需要使用匿名函数,没有更简单的方法。
更新
已有一个插件: jQuery.hoverIntent()
。 无需亲自制作。 它易于使用,只需将mouseleave
事件替换为:
$('#someNum').hoverIntent(jQuery.noop, function() { // your function goes here });
这样做非常重要,因为第一个是mouseenter
处理程序,第二个是mouseleave
处理程序。 jQuery.noop
是一个空函数,它实际上与function() {}
。
这可以工作,也可以在循环中使用。
var x = "OK"; setTimeout(alertOK.bind(null,x), 3000); x = "Would be WRONG"; console.log("before timeout:", x); function alertOK(x){ console.log("after timeout:",x); }
因为你正在写一个字符串,它不像实际的闭包那样聪明。
$('.mainNav2 > li').mouseleave(function(){ var someNum = Math.random(); $(this).attr('id', someNum); var t = setTimeout(function() { HideMenu(someNum); }, 200); $('li.clicked').mouseenter(function() { clearTimeout(t); }); }); function HideMenu(id) { $('#'+id).removeClass('clicked'); }