如果我在Javascript事件处理程序中进行DOM更改,那些更改是以递增方式呈现的,还是仅在结束时呈现一次?

use*_*609 10 html javascript dom

假设我有以下javascript事件处理程序:

function handleEvent(e){
    document.body.style.backgroundColor = 'green';
    longRunningFunction();
    document.body.style.backgroundColor = 'red';
}
Run Code Online (Sandbox Code Playgroud)

浏览器是否会首先显示绿色背景,然后将其切换为红色?或直接显示红色背景?

根据我的测试,它直接在事件处理程序的末尾显示红色.但这是规范的一部分,还是偶然发生了如何实现浏览器?

更新:

我应该澄清一点,我并非"瞄准"这种效果.相反,我希望有一些保障,它并没有发生.我的一些事件处理程序改变了很多东西,如果我可以假设没有任何中间状态被渲染,它会让我的生活更轻松.

aps*_*ers 11

以下是JavaScript执行环境中将发生的情况:

  1. document.body.style.backgroundColor将其价值改为'green'.
  2. 将运行长时间运行的进程.
  3. document.body.style.backgroundColor将其价值改为'red'.

backgroundColor如果JavaScript线程被阻止,则未指定属性中的更改将如何影响页面的外观.

这是一个例子.如果单击该单词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);
Run Code Online (Sandbox Code Playgroud)
<div>hello</div>
Run Code Online (Sandbox Code Playgroud)

这是因为长时间运行的阻止JavaScript函数会阻止浏览器重新绘制以响应CSS属性更改的呈现引擎.这不是指定的行为,而是所有浏览器的实现现实.请参阅当我的脚本执行一些繁重的处理时,如何强制浏览器重绘?对于类似的问题.

我认为任何给定的浏览器都可以选择与JavaScript线程并行运行一个单独的重绘线程,但我不相信任何主流浏览器目前都这样做.这种方法可能存在固有的竞争条件复杂性; 我从来没有写过浏览器,所以我不知道.


如果显示中间状态,可以setTiemout在设置backgroundColor为绿色后使用非常快速的调用,清除JavaScript函数堆栈并允许渲染器重绘页面:

function handleEvent(e){
    document.body.style.backgroundColor = 'green';
    setTimeout(function() {
        longRunningFunction();
        document.body.style.backgroundColor = 'red';
    }, 4);
}
Run Code Online (Sandbox Code Playgroud)

这将排队longRunningFunction和第二个颜色更改在将来的4毫秒内运行.在闲置4毫秒期间,渲染器有机会重绘页面.