setTimeout()和设置参数

发布于 2024-10-20 02:38:41 字数 778 浏览 3 评论 0原文

我有一些 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);

为什么它不能按编写的方式工作,我可以将变量作为参数传递到函数中?

I have some jQuery code that looks like this:

$('.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.

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.asp my syntax is correct, but I can only get the HideMenu function called from the setTimeout if I write it like this:

var t = setTimeout(HideMenu, 300);

Why isn't it working as written, where I can pass a variable into the function as a parameter?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

猫九 2024-10-27 02:38:41

虽然标记的正确答案是实现这一目标的一种方法......但我不认为这是正确的。

请参阅附件 JS Fiddle:
http://jsfiddle.net/PWHw3/

我们在这里所做的基本上是:

setTimeout(function, timeout, param);

示例:

var test = function(a){
    var b = (a) ? a : "fail";
    alert(b);
};
setTimeout(test, 500, "works");

这对我有用,并且消除了传递两个函数的需要。

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/

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.

和我恋爱吧 2024-10-27 02:38:41

为了使其工作,并且在不使用 setTimeout 的令人讨厌的 eval 版本的情况下进行更改:

var t = setTimeout("HideMenu(someNum)", 200);

改为:

var t = setTimeout(function(s) {  
                 return function() { HideMenu(s) } }(someNum), 200);

这样,您可以将 someNum 的值传递到作用域中的变量 ssetTimeout 的。

To make it work, and do it without using the nasty eval version of setTimeout change:

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.

西瓜 2024-10-27 02:38:41

setTimeout 接受一个函数和毫秒延迟。该函数可以是函数引用,也可以是在超时触发时进行计算的字符串。您当前的序列如下所示:

  • mouseleave 函数

    • 为变量someNum分配一个值。 someNum 的范围为
      当前函数
    • 设置一个计时器,在 200 毫秒后评估字符串“HideNum(someNum)”
    • 结束函数,离开函数作用域
  • 200ms 传递

  • "HideNum(someNum)" 被评估。它应该抛出异常,因为变量 someNum 未定义。这就是为什么 HideNum 没有被调用 - 检查控制台中的错误。

你想要的是一个函数引用,它将把你的 someNum 保持在范围内(通过闭包 - 你可能想阅读)。

setTimeout(function() { 
  HideNum(someNum); 
}, 200);

您会发现 Mozilla 文档是 JavaScript 的更好参考。这是 window.setTimeout 文档。

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:

  • 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
  • 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.

What you want is a function reference, which will keep your someNum in scope (via closure - which you might want to read up on).

setTimeout(function() { 
  HideNum(someNum); 
}, 200);

You'll find the Mozilla docs a better reference for JavaScript. Here's the window.setTimeout docs.

吃兔兔 2024-10-27 02:38:41

您想要做的是创建一个匿名函数并在 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);
  });
});

What you want to do is to create an anonymous function and call that in the setTimeout call.

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:

$('.mainNav2 > li').mouseleave(function() {
  var $this = $(this);
  var t = setTimeout(function() {
    $this.removeClass('clicked');
  }, 200);
  $('li.clicked').mouseenter(function() {
    clearTimeout(t);
  });
});
萌化 2024-10-27 02:38:41

还有更多方法可以做到这一点。

1. 使用匿名函数(推荐)

setTimeout(function() {
    hideMenu('someNum');
}, 200);

2. setTimeoutsetInterval 有一个隐藏功能:可以指定超时后的参数。

setTimeout(hideMenu, 200, params);

由于您已经在使用 jQuery,因此您不应该创建一个单独的函数,而应该扩展 jQuery 的原型,如下所示:

jQuery.fn.hideMenu = function() {
    this.removeClass('clicked');
    return this;
};

用法:

$('#num').hideMenu();

请注意,当您执行以下操作时,不需要将 this 传递给 jQuery正在扩展它的原型,因为它已经传递给了 jQuery。并且需要 return this; 来保持链接的能力。

如果你选择这种方式,你需要使用匿名函数,没有更简单的方法了。


更新

已经有一个插件: jQuery.hoverIntent()< /a>.无需自己制作。它很容易使用,只需将 mouseleave 事件替换为:

$('#someNum').hoverIntent(jQuery.noop, function() {
    // your function goes here
});

这样做很重要,因为第一个是 mouseenter 处理程序,第二个是 >mouseleave 处理程序。 jQuery.noop 是一个空函数,它实际上与 function() {} 相同。

There are more ways to do that.

1. Use an anonymous function (recommended)

setTimeout(function() {
    hideMenu('someNum');
}, 200);

2. setTimeout and setInterval have a hidden feature: you can specify parameters after the timeout.

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.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.

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:

$('#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() {}.

倾城月光淡如水﹏ 2024-10-27 02:38:41

这有效,并且也可以在循环中使用。

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);
}

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);
}

我们的影子 2024-10-27 02:38:41

因为你正在编写一个字符串,它并不像实际的闭包那么智能。

$('.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');
}

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');
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文