假设我有以下javascript事件处理程序:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
longRunningFunction();
document.body.style.backgroundColor = 'red';
}
浏览器是否会首先显示绿色背景,然后将其切换为红色?或直接显示红色背景?
根据我的测试,它直接在事件处理程序的末尾显示红色。但这是规范的一部分,还是偶然发生了如何实现浏览器?
更新
我应该澄清一点,我不是"瞄准"为了这个效果。相反,我想要保证不发生。我的一些事件处理程序改变了很多东西,如果我可以假设没有渲染任何中间状态,那么它会让我的生活更轻松。
答案 0 :(得分:11)
以下是JavaScript执行环境中会发生的事情:
document.body.style.backgroundColor
会将其值更改为'green'
。document.body.style.backgroundColor
会将其值更改为'red'
。如果JavaScript线程被阻止,则未指定backgroundColor
属性中的更改将如何影响页面的外观。
这是一个例子。如果您点击单词hello
,您会看到稍微延迟,然后背景会变为红色:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
longRunningFunction();
document.body.style.backgroundColor = 'red';
}
function longRunningFunction() {
for(var i=0; i<2000000000; ++i) { +i; }
}
document.body.addEventListener("click", handleEvent);
<div>hello</div>
这是因为长时间运行的阻止JavaScript函数会阻止浏览器重新绘制以响应CSS属性更改的呈现引擎。这不是指定的行为,而是所有浏览器的实现现实。有关类似问题,请参阅How can I force the browser to redraw while my script is doing some heavy processing?。
我认为任何给定的浏览器都可以选择与JavaScript线程同时运行一个单独的重绘线程,但我不认为任何主流浏览器目前都这样做。这种方法可能存在固有的竞争条件复杂性;我从来没有写过浏览器,所以我不知道。
如果希望显示中间状态,则可以在将setTiemout
设置为绿色后使用非常快速的backgroundColor
调用,以清除JavaScript函数堆栈并允许渲染器重绘页面:
function handleEvent(e){
document.body.style.backgroundColor = 'green';
setTimeout(function() {
longRunningFunction();
document.body.style.backgroundColor = 'red';
}, 4);
}
将longRunningFunction
和第二个颜色更改排队,以便将来在4毫秒内运行。在闲置4毫秒期间,渲染器有机会重绘页面。
答案 1 :(得分:0)
这是否说明了您的目标?
function handleEvent(e){
document.body.style.backgroundColor = 'green';
alert();
document.body.style.backgroundColor = 'red';
}