我正在尝试使用闭包来确保函数只能执行一次。听起来很简单,它的工作原理如下:
function runOnce(fn) // returns copy of fn which can only execute once
{
var ran = false;
return function()
{
if (!ran)
{
fn();
ran = true;
}
};
}
我已经测试过这样的功能:
function lazyLoadGrid(event, ui)
{
alert('hi');
}
var test1 = runOnce(lazyLoadGrid);
var test2 = runOnce(lazyLoadGrid);
test1();
test2();
test1();
test2();
它按预期工作 - 'hi'被提醒两次。
但后来我尝试使用runOnce(lazyLoadGrid)作为jQuery UI事件的回调:
$('.accordion').each(function()
{
$(this).accordion({ autoHeight: false, change: runOnce(lazyLoadGrid) });
});
疯狂随之而来。我期望的是,当首次打开手风琴时,页面上的每个'手风琴'都会运行一次lazyLoadGrid()。相反,闭包回调似乎表现得好像它们都引用了'ran'的相同副本。 lazyLoadGrid()在我第一次打开任何手风琴时运行,然后再也不会为任何其他手风琴再次运行。记录'run'的前置条件值表示每次在第一个之后点击任何手风琴时它都是'true'。
对此有何解释?值得注意的是,我有一个奇怪的页面,嵌套的手风琴,以及多个包含手风琴的jQuery UI标签。更糟糕的是,当我切换标签时,闭合实际上确实在任何给定标签的第一个打开的手风琴上运行。任何建议都非常感谢。
答案 0 :(得分:1)
怎么样:
function runOnce(fn) {
return function(){
fn();
fn = function(){};
}
}
// test
var foo = function(){
console.log('bar');
}
foo = runOnce(foo);
foo(); // bar
foo();
foo();
答案 1 :(得分:1)
我相信你遇到的麻烦是因为你所谓的“手风琴”实际上是一个“小组”。手风琴由一组中的所有小组组成。听起来你想要每个面板运行一次,而不是每个手风琴一次。以下演示通过在页面上包含两个手风琴来说明该概念。请注意,lazyLoadGrid()
运行两次,每个手风琴一次:
相反,您要做的是创建自定义事件并在每个面板上调用该事件。然后你可以利用jQuery的内置.one()
方法,这会导致为每个元素调用一次事件处理程序:
$('.accordion').accordion({
autoHeight: false,
change: function(e, ui) {
ui.newHeader.trigger("activated");
}
});
$('.accordion > h3').one("activated", lazyLoadGrid);
答案 2 :(得分:0)
我认为因为函数需要指定event参数。 试试这个:
$('.accordion').each(function() {
$(this).accordion({ autoHeight: false, change: runOnce(arguments[0],lazyLoadGrid) });
});
尝试直接使用函数lazyLoadGrid,或者如果必须使用runOnce,则必须将参数[0](即事件)指定为函数中的参数
- 编辑 -
抱歉,我忘了把事件放在功能中