javascript - jQuery 代码太冗长,希望获得有关如何使其更短的指示

标签 javascript jquery

<分区>

我有一些 jQuery 代码,我希望获得有关如何减少和缩短行数的评论和指示。

$('#p1').click(function() {
    $('#list').fadeOut(450);
    $('#q1').delay(600).fadeIn(450)
});
$('#p2').click(function() {
    $('#list').fadeOut(450);
    $('#q2').delay(600).fadeIn(450)
});
$('#p3').click(function() {
    $('#list').fadeOut(450);
    $('#q3').delay(600).fadeIn(450)
});
$('#p4').click(function() {
    $('#list').fadeOut(450);
    $('#q4').delay(600).fadeIn(450)
});

...

$('#p12').click(function() {
    $('#list').fadeOut(450);
    $('#q12').delay(600).fadeIn(450)
});
$('#p13').click(function() {
    $('#list').fadeOut(450);
    $('#q13').delay(600).fadeIn(450)
});

这段代码可以更好地优化吗?或者至少不那么冗长?

最佳答案

您可以使用 for 循环,但您应该确保循环计数器的值进入 click 事件处理程序的正确范围:

var clickHandler = function(k) {
    return function() {
        $('#list').fadeOut(450);
        $('#q' + k).delay(600).fadeIn(450);
    };
};
for (var i = 1; i < 14; ++i) {
    $('#p' + i).click(clickHandler(i));
}

否则 delayfadeIn 将专门应用于 #q13 元素,因为实际计数器(其最终值为 13)将进入关闭状态。


编辑:由于很多答案在这里都弄错了,我将尝试更准确地解释这段代码中发生的事情,因为它看起来很困惑。

将点击处理程序直接注入(inject)循环的“自然”解决方案如下:

for(var i = 1; i < 14; i++) {
    $('#p'+i).click(function() {
        $('#list').fadeOut(450);
        $('#q'+i).delay(600).fadeIn(450)
    });
}

但这完全不等同于扩展形式,扩展形式将13个变体依次列出。问题是虽然这里确实创建了 13 个函数,但它们都关闭了同一个变量 i,其值发生了变化。它最终到达 13 的值,循环结束。

一段时间后,附加到 #p1...#p13 元素的函数被调用(当其中一个元素被点击时),它们使用最终值。这导致只有 #q13 被激活。

这里需要做的是做一个叫做lambda lifting的事情。并消除自由变量 i,它的值被无意中改变了。一种常见的技术是提供一个“工厂函数”,它接受我们变量的值并输出一个我们将用作事件处理程序的实际函数:

var clickHandler = function(k) {
    return function() {
        $('#list').fadeOut(450);
        $('#q' + k).delay(600).fadeIn(450);
    };
};

由于 k 参数的范围是 clickHandler 的局部范围,因此每次调用 clickHandler 都会得到不同的 k 变量.因此,从 clickHandler 返回的函数对不同的变量关闭,而这些变量又可以有不同的值。这正是我们所需要的。然后我们可以从循环中调用 clickHandler,将计数器的值传递给它:

for (var i = 1; i < 14; ++i) {
    $('#p' + i).click(clickHandler(i));
}

我希望这能让区别更清楚一些。


编辑:正如 Esailija 在评论中指出的那样,也可以使用 jQuery.each 来实现类似的效果:

$.each(new Array(13), function(idx) {
    $('#p' + (idx + 1)).click(function() {
        $('#list').fadeOut(450);
        $('#q' + idx).delay(600).fadeIn(450);
    });
});

如果您已经意识到我在上面概述的闭包/范围界定问题,那么这可能是您的首选解决方案。

关于javascript - jQuery 代码太冗长,希望获得有关如何使其更短的指示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8277915/

相关文章:

javascript - 在 jQuery 对话框打开后找到一个元素

Javascript JSON 数据解析问题, bool 值显示不正确

javascript - 如何使用 JQuery/CSS 在单击按钮时将 div 面板移动到所有其他 div 面板下方?

jquery - 我怎样才能用 jquery 获得这种效果(在高度上)?

javascript - 如何使用我的 JS 变量作为数组键?

javascript - 带区间变量的 rxjs 无限循环

javascript - 需要在 HTML/JS 应用程序中灰显问题(以单选按钮作为答案)?

javascript - 输入在 iPad、CSS、LI、div、剪辑问题上不起作用?

javascript - 当发生 2 个不同的事件时运行相同的代码

javascript - 将变量值与元素值进行比较