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

时间:2015-05-20 19:16:12

标签: javascript html dom

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

function handleEvent(e){
    document.body.style.backgroundColor = 'green';
    longRunningFunction();
    document.body.style.backgroundColor = 'red';
}

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

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

更新

我应该澄清一点,我不是"瞄准"为了这个效果。相反,我想要保证发生。我的一些事件处理程序改变了很多东西,如果我可以假设没有渲染任何中间状态,那么它会让我的生活更轻松。

2 个答案:

答案 0 :(得分:11)

以下是JavaScript执行环境中会发生的事情:

  1. document.body.style.backgroundColor会将其值更改为'green'
  2. 将运行一个长时间运行的进程。
  3. document.body.style.backgroundColor会将其值更改为'red'
  4. 如果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';
}