如何用jQuery编写更优雅高效的迭代淡入淡出函数
嘿,我太懂你这种被嵌套回调堆成“金字塔”的痛苦了——这玩意儿俗称「回调地狱」,不仅看着闹心,以后改代码也得一层一层扒,简直是维护噩梦!咱们来把这段淡入淡出的代码彻底翻新,变得清爽又优雅~
先还原一下你现在的代码(补全了没写完的部分):
$('span[data-i18n="text.about"]').click(function () { $('#one').fadeTo(2000, 1, function() { $('#one').fadeTo(2000, 0, function() { $('#two').fadeTo(2000, 1, function() { $('#two').fadeTo(2000, 0, function() { $('#three').fadeTo(2000, 1, function() { $('#three').fadeTo(2000, 0, function() { $('#four').fadeTo(2000, 1, function() { // 后面还得继续嵌套... }); }); }); }); }); }); }); });
下面给你两种最实用的优化方案,任选其一都能解决问题:
方案1:用jQuery Deferred + 链式调用
jQuery的动画方法(比如fadeTo)会返回一个Deferred对象,支持.then()链式调用,当前动画完成后才会执行下一个步骤,完美避开嵌套:
// 先封装单个元素的淡入淡出逻辑 function fadeElement(element) { return $(element).fadeTo(2000, 1).fadeTo(2000, 0); } $('span[data-i18n="text.about"]').click(function () { // 按顺序链式执行,逻辑一目了然 fadeElement('#one') .then(() => fadeElement('#two')) .then(() => fadeElement('#three')) .then(() => fadeElement('#four')) // 要加新元素?直接在后面加个.then就行 });
方案2:用async/await + 循环(最简洁直观)
如果你用的是支持ES6+的环境,async/await能让代码像同步逻辑一样清晰,完全告别回调:
$('span[data-i18n="text.about"]').click(async function () { // 把要动画的元素按顺序放进数组 const targetElements = ['#one', '#two', '#three', '#four']; // 循环逐个执行动画,await会等待当前动画完成再走下一个 for (const elem of targetElements) { // .promise()把jQuery动画转成标准Promise,让await能识别 await $(elem).fadeTo(2000, 1).fadeTo(2000, 0).promise(); } });
另外你提到初始透明度设为null,这个完全不用操心——jQuery的fadeTo会自动识别元素的当前透明度状态,从现有值平滑过渡到目标值,不需要额外处理。如果要强制初始状态为透明,只需要在页面加载时加一行:
$('#one, #two, #three, #four').css('opacity', 0);
这两种写法都比原来的嵌套结构优雅太多,以后要加新元素、改动画时长,直接改数组或者封装函数就行,维护成本低到离谱~
内容的提问来源于stack exchange,提问作者Nixen85
相关产品推荐
相关产品推荐

