jQuery 按需使用 javascript 强制 DOM 重绘
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16875690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
force DOM redraw with javascript on demand
提问by javigzz
The title of the question expresses what I think is the ultimate question behind my particular case.
问题的标题表达了我认为是我的特定案例背后的最终问题。
My case: Inside a click handler, I want to make an image visible (a 'loading' animation) right before a busy function starts. Then I want to make it invisible again after the function has completed. Instead of what I expected I realize that the image never becomes visible. I guess that this is due to the browser waiting for the handler to end, before it can do any redrawing (I am sure there are good performance reasons for that).
我的情况:在点击处理程序中,我想在繁忙的功能开始之前使图像可见(“加载”动画)。然后我想在功能完成后再次使其不可见。我意识到图像永远不会变得可见,而不是我的预期。我猜这是由于浏览器等待处理程序结束,然后才能进行任何重绘(我确信这有很好的性能原因)。
The code (also in this fiddle: http://jsfiddle.net/JLmh4/2/)
代码(也在这个小提琴中:http: //jsfiddle.net/JLmh4/2/)
html:
html:
<img id="kitty" src="http://placekitten.com/50/50" style="display:none">
<div><a href="#" id="enlace">click to see the cat</a> </div>
js:
js:
$(document).ready(function(){
$('#enlace').click(function(){
var kitty = $('#kitty');
kitty.css('display','block');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec)
{
var endtime= new Date().getTime() + usec;
while (new Date().getTime() < endtime)
;
}
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.css('display','none');
});
});
I have added the alert
call right after the sleepStupidly
function to show that in that moment of rest, the browser does redraw, but not before. I innocently expected it to redraw right after setting the 'display' to 'block';
我alert
在sleepStupidly
函数之后添加了调用,以显示在休息的那一刻,浏览器会重绘,但之前不会。我天真地希望它在将“显示”设置为“阻止”后立即重绘;
For the record, I have also tried appending html tags, or swapping css classes, instead of the image showing and hiding in this code. Same result.
作为记录,我还尝试附加 html 标记或交换 css 类,而不是在此代码中显示和隐藏图像。结果一样。
After all my research I think that what I would need is the ability to force the browser to redrawand stop every other thing until then.
经过我所有的研究,我认为我需要的是能够强制浏览器重绘并在此之前停止所有其他事情。
Is it possible? Is it possible in a crossbrowser way? Some plugin I wasn't able to find maybe...?
是否可以?是否有可能以跨浏览器的方式?一些我找不到的插件也许......?
I thought that maybe something like 'jquery css callback' (as in this question: In JQuery, Is it possible to get callback function after setting new css rule?) would do the trick ... but that doesn't exist.
我认为可能像'jquery css callback'(如在这个问题中:在JQuery中,是否有可能在设置新的css规则后获得回调函数?)可以解决问题......但这并不存在。
I have also tried to separte the showing, function call and hiding in different handlers for the same event ... but nothing. Also adding a setTimeout
to delay the execution of the function (as recommended here: Force DOM refresh in JavaScript).
我还尝试将显示、函数调用和隐藏在同一事件的不同处理程序中分开......但没有。还添加了一个setTimeout
来延迟函数的执行(如这里推荐的:在 JavaScript 中强制 DOM 刷新)。
Thanks and I hope it also helps others.
谢谢,我希望它也能帮助其他人。
javier
哈维尔
EDIT (after setting my preferred answer):
编辑(设置我的首选答案后):
Just to further explain why I selected the window.setTimeout strategy. In my real use case I have realized that in order to give the browser time enough to redraw the page, I had to give it about 1000 milliseconds (much more than the 50 for the fiddle example). This I believe is due to a deeper DOM tree (in fact, unnecessarily deep). The setTimeout let approach lets you do that.
只是为了进一步解释为什么我选择 window.setTimeout 策略。在我的实际用例中,我意识到为了给浏览器足够的时间来重绘页面,我必须给它大约 1000 毫秒(比小提琴示例中的 50 毫秒多得多)。我相信这是由于更深的 DOM 树(实际上,不必要地深)。setTimeout let 方法可以让您做到这一点。
采纳答案by Marat Tanalin
Use window.setTimeout()
with some short unnoticeable delay to run slow function:
使用window.setTimeout()
一些短暂的不明显的延迟来运行慢功能:
$(document).ready(function() {
$('#enlace').click(function() {
showImage();
window.setTimeout(function() {
sleepStupidly(4000);
alert('now you do see it');
hideImage();
}, 50);
});
});
回答by sdespont
Use JQuery show
and hide
callbacks (or other way to display something like fadeIn/fadeOut).
使用 JQueryshow
和hide
回调(或其他方式来显示诸如淡入/淡出之类的东西)。
$(document).ready(function () {
$('#enlace').click(function () {
var kitty = $('#kitty');
// see: http://unixpapa.com/js/sleep.html
function sleepStupidly(usec) {
var endtime = new Date().getTime() + usec;
while (new Date().getTime() < endtime);
}
kitty.show(function () {
// simulates bussy proccess, calling some function...
sleepStupidly(4000);
// when this triggers the img style do refresh!
// but not before
alert('now you do see it');
kitty.hide();
});
});
});
回答by ronnykaram
To force redraw, you can use offsetHeight or getComputedStyle().
要强制重绘,您可以使用 offsetHeight 或 getComputedStyle()。
var foo = window.getComputedStyle(el, null);
or
或者
var bar = el.offsetHeight;
"el" being a DOM element
“el”是一个 DOM 元素
回答by user3177944
What worked for me is setting the following:
对我有用的是设置以下内容:
$(element).css('display','none');
After that you can do whatever you want, and eventually you want to do:
之后你可以做任何你想做的事情,最终你想做:
$(element).css('display','block');
回答by Michael Trojanek
I do not know if this works in your case (as I have not tested it), but when manipulating CSS with JavaScript/jQuery it is sometimes necessary to force redrawing of a specific element to make changes take effect.
我不知道这是否适用于您的情况(因为我尚未对其进行测试),但是在使用 JavaScript/jQuery 操作 CSS 时,有时需要强制重绘特定元素以使更改生效。
This is done by simply requesting a CSS property.
这是通过简单地请求一个 CSS 属性来完成的。
In your case, I would try putting a kitty.position().left;
before the function call prior to messing with setTimeout
.
在您的情况下,我会尝试kitty.position().left;
在弄乱setTimeout
.