jQuery setTimeout() 和设置参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5169020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
setTimeout() and setting parameters
提问by Ben
I have some jQuery code that looks like this:
我有一些看起来像这样的 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');
}
It's purpose is to hide a mega menu on mouse leave, but also takes into account accidental mouse leaves, by using a 300 millisecond setTimeout. If the user brings the mouse pointer back into the li within 300 milliseconds, the menu is not hidden because clearTimout(t) is called.
它的目的是通过使用 300 毫秒的 setTimeout 在鼠标离开时隐藏一个超级菜单,但也考虑到意外的鼠标离开。如果用户在 300 毫秒内将鼠标指针放回 li,则菜单不会隐藏,因为调用了 clearTimout(t)。
The problem is when the user DOES intent to mouseout, the function in the setTimout is not being called. According to this page: http://www.w3schools.com/js/js_timing.aspmy syntax is correct, but I can only get the HideMenu function called from the setTimeout if I write it like this:
问题是当用户确实想要鼠标移出时,不会调用 setTimout 中的函数。根据这个页面:http: //www.w3schools.com/js/js_timing.asp我的语法是正确的,但如果我这样写,我只能从 setTimeout 调用 HideMenu 函数:
var t = setTimeout(HideMenu, 300);
Why isn't it working as written, where I can pass a variable into the function as a parameter?
为什么它不像写的那样工作,我可以将变量作为参数传递给函数?
回答by Roi
While the marked correct answer is one method of achieving this... I don't believe it is the correct.
虽然标记的正确答案是实现这一目标的一种方法......我不相信这是正确的。
See the attached JS Fiddle: http://jsfiddle.net/PWHw3/
请参阅随附的 JS Fiddle:http: //jsfiddle.net/PWHw3/
What we are doing here basically is:
我们在这里所做的基本上是:
setTimeout(function, timeout, param);
Example:
例子:
var test = function(a){
var b = (a) ? a : "fail";
alert(b);
};
setTimeout(test, 500, "works");
This works for me, and eliminates the needs to pass through two functions.
这对我有用,并且不需要通过两个函数。
回答by Martin Jespersen
To make it work, and do it without using the nasty eval version of setTimeout change:
为了使它工作,并且在不使用 setTimeout 更改的令人讨厌的 eval 版本的情况下执行此操作:
var t = setTimeout("HideMenu(someNum)", 200);
to this:
对此:
var t = setTimeout(function(s) {
return function() { HideMenu(s) } }(someNum), 200);
This way you pass the value of someNum
into the variable s
in the scope of the setTimeout
.
通过这种方式传递的值someNum
到变量s
中的范围setTimeout
。
回答by Sam Foster
setTimeout
accepts a function and a millisecond delay. The function can be either a function reference or a string that will get evaluated when the timeout fires. Your current sequence looks like this:
setTimeout
接受一个函数和一个毫秒的延迟。该函数可以是函数引用或在超时触发时将被评估的字符串。您当前的序列如下所示:
mouseleave function
- assign variable
someNum
a value. someNum is scoped to the current function - set a timer to evaluate the string
"HideNum(someNum)"
after 200ms. - end function, leave function scope
- assign variable
200ms passes
"HideNum(someNum)"
is evaluated. It should throw an exception as the variable someNum is undefined. That's why HideNum is not being called - check for errors in your console.
鼠标离开函数
- 给变量
someNum
赋值。someNum 作用域为当前函数 - 设置一个计时器以
"HideNum(someNum)"
在 200 毫秒后评估字符串。 - 结束函数,离开函数作用域
- 给变量
200 毫秒过去
"HideNum(someNum)"
被评估。它应该抛出异常,因为变量 someNum 未定义。这就是没有调用 HideNum 的原因 - 检查控制台中的错误。
What you want is a function reference, which will keep your someNum in scope (via closure - which you might want to read up on).
您想要的是一个函数引用,它将使您的 someNum 保持在范围内(通过闭包 - 您可能想要阅读)。
setTimeout(function() {
HideNum(someNum);
}, 200);
You'll find the Mozilla docs a better reference for JavaScript. Here's the window.setTimeoutdocs.
您会发现 Mozilla 文档是 JavaScript 的更好参考。这是window.setTimeout文档。
回答by Linus Gustav Larsson Thiel
What you want to do is to create an anonymous function and call that in the setTimeout call.
您想要做的是创建一个匿名函数并在 setTimeout 调用中调用它。
setTimeout(function() { HideMenu(someNum) }, 200);
If I correctly understand what you want to do, though, you shouldn't have to bother with setting an id and all that stuff. Something like this should do it:
但是,如果我正确理解您想要做什么,您就不必费心设置 id 和所有这些东西。像这样的事情应该这样做:
$('.mainNav2 > li').mouseleave(function() {
var $this = $(this);
var t = setTimeout(function() {
$this.removeClass('clicked');
}, 200);
$('li.clicked').mouseenter(function() {
clearTimeout(t);
});
});
回答by nyuszika7h
There are more ways to do that.
有更多方法可以做到这一点。
1.Use an anonymous function (recommended)
1.使用匿名函数(推荐)
setTimeout(function() {
hideMenu('someNum');
}, 200);
2.setTimeout
and setInterval
have a hidden feature: you can specify parameters after the timeout.
2.setTimeout
并setInterval
有一个隐藏功能:可以在超时后指定参数。
setTimeout(hideMenu, 200, params);
Since you're already using jQuery, you shouldn't make a separate function, but extend jQuery's prototype instead, like this:
既然你已经在使用 jQuery,你不应该创建一个单独的函数,而是扩展 jQuery 的原型,就像这样:
jQuery.fn.hideMenu = function() {
this.removeClass('clicked');
return this;
};
Usage:
用法:
$('#num').hideMenu();
Notice that you don't need to pass this
to jQuery when you're extending its prototype, because it's already passed to jQuery. And return this;
is required to keep the ability of chaining.
请注意,this
在扩展其原型时不需要传递给 jQuery,因为它已经传递给 jQuery。并且return this;
需要保持链接的能力。
If you choose this way, you need to use an anonymous functions, there's no easier way.
如果选择这种方式,则需要使用匿名函数,没有比这更简单的方法了。
Update
更新
There's already a plugin for that: jQuery.hoverIntent()
. No need to make it yourself. It's easy to use, just replace mouseleave
event with this:
已经有一个插件:jQuery.hoverIntent()
. 没必要自己做。它很容易使用,只需将mouseleave
事件替换为:
$('#someNum').hoverIntent(jQuery.noop, function() {
// your function goes here
});
It's important to do it this way, since the first one is the mouseenter
handler, and the second is the mouseleave
handler. jQuery.noop
is an empty function, it's effectively the same as function() {}
.
这样做很重要,因为第一个是mouseenter
处理程序,第二个是mouseleave
处理程序。jQuery.noop
是一个空函数,它实际上与function() {}
.
回答by Lovro
This works, and can be used within a loop also.
这有效,也可以在循环中使用。
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);
}
回答by Lightness Races in Orbit
Because you're writing a string, which isn't as intelligent as an actual closure.
因为您正在编写一个字符串,它不像实际的闭包那样智能。
$('.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');
}