each循环中Div类样式添加后不显示问题求助
问题分析与解决办法
这问题我之前也碰到过,核心原因是浏览器的JavaScript执行和UI渲染共用同一个主线程。你现在的代码逻辑是:
- 给loader加类
- 立刻执行耗时的
each循环(同步阻塞主线程) - 循环结束后马上移除类
因为主线程被耗时的循环占满了,浏览器根本没机会去重绘DOM、应用loading-page的样式——等循环跑完,你又立刻把类去掉了,所以视觉上完全看不到加载效果。而调试时断点暂停了JS执行,浏览器终于有时间完成重绘,所以加载图就能显示出来了。
修复方案
最简单的解决办法是把耗时的操作放到setTimeout里,让浏览器先完成UI更新,再执行耗时任务:
$("#btnApplyDefaults").on('click', function (e) { $('#loader').addClass("loading-page"); // 用setTimeout把耗时任务放到事件队列末尾,给浏览器留重绘时间 setTimeout(function() { $('#pricingSheetItems tr').filter(':has(:checkbox:checked)').each(function() { // 这里放你的耗时操作 }); $('#loader').removeClass("loading-page"); }, 0); // 0毫秒延迟足以让浏览器先处理UI渲染 });
为什么这个方法有效?
setTimeout(fn, 0)并不会立刻执行回调,而是把它加入到浏览器的事件队列中。当前的JS执行栈(也就是addClass这行代码)执行完后,浏览器会先处理UI渲染,再去执行事件队列里的回调函数——这样加载样式就能正常显示出来了。
如果你的"Do some stuff"是非常耗时的计算(比如处理大量数据),更推荐用Web Worker来处理,完全不阻塞主线程,但对于中等耗时的操作,setTimeout就足够解决问题了。
另外提一句,你的loading-page CSS里position: absolute,最好确保它的父元素设置了position: relative,不然加载图可能会跑到页面角落去,但你调试时能看到,说明这个不是当前的核心问题。
内容的提问来源于stack exchange,提问作者M Kenyon II
相关产品推荐
相关产品推荐

