api*_*art 98 html javascript dom google-chrome
我希望我不会自欺欺人,但我想了解这两行代码中发生了什么:
document.body.innerHTML = 'something';
alert('something else');
Run Code Online (Sandbox Code Playgroud)
我观察到的是在HTML更新之前警报显示(或者它可能有但是页面没有刷新/重新绘制/无论如何)
检查这个codepen看看我的意思.
请注意,即使将alert在setTimeout(..., 0)没有帮助.看起来innerHTML实际更新页面需要更多的事件循环.
编辑:
我忘了提到我使用Chrome并没有检查其他浏览器.看起来它只在Chrome中可见.尽管如此,我仍然感兴趣为什么会发生这种情况.
jer*_*red 130
设置innerHTML是同步的,您可以对DOM进行大多数更改.但是,渲染网页是另一回事.
(请记住,DOM代表"文档对象模型".它只是一个"模型",是数据的表示.用户在屏幕上看到的是该模型应该如何显示的图片.因此,更改模型不会立即改变图片 - 需要一些时间来更新.)
运行JavaScript并呈现网页实际上是分开进行的.把它简单地说,首先是所有的JavaScript代码的页面运行(从事件循环-看看这个优秀的视频更多的细节),然后后,浏览器呈现的网页进行任何更改用户看到的.这就是为什么"阻塞"是如此重要的原因 - 运行计算密集型代码会阻止浏览器通过"运行JS"步骤并进入"渲染页面"步骤,导致页面冻结或断断续续.
Chrome的管道如下所示:
如您所见,所有JavaScript都是先发生的.然后页面被样式化,布局,绘制和合成 - "渲染".并非所有此管道都将执行每一帧.这取决于更改的页面元素(如果有)以及如何重新呈现它们.
注意:alert()同步并在JavaScript步骤中执行,这就是在您看到网页更改之前出现警告对话框的原因.
您现在可能会问:"坚持,管道中的'JavaScript'步骤究竟会运行什么?我的所有代码每秒运行60次吗?" 答案是"不",它可以追溯到JS事件循环的工作原理.JS代码只有在堆栈中才会运行 - 从事件监听器,超时等等.请参阅上一个视频(真的).
https://developers.google.com/web/fundamentals/performance/rendering/
d-_*_*_-b 26
是的,它是同步的,因为它可以工作(继续,在你的控制台中键入它):
document.body.innerHTML = 'text';
alert(document.body.innerHTML);// you will see a 'text' alert
Run Code Online (Sandbox Code Playgroud)
您在看到页面更改之前看到警报的原因是浏览器呈现需要更多时间,并且不如您的javascript逐行执行.
该innerHTML财产实际并得到同步更新,但视觉重绘,这种变化会导致异步发生.
视觉呈现DOM在Chrome中是异步的,直到当前的JavaScript函数堆栈清除并且浏览器可以自由接受新事件之后才会发生.其他浏览器可能使用单独的线程来处理JavaScript代码和浏览器呈现,或者当警报停止执行另一个事件时,它们可能会让某些事件获得优先级.
您可以通过两种方式看到这一点:
如果你for(var i=0; i<1000000; i++) { }在警报之前添加,你已经给浏览器足够的时间来重绘,但它没有,因为函数堆栈还没有清除(add仍在运行).
如果你延迟alert通过异步setTimeout(function() { alert('random'); }, 1),重绘过程将超过setTimeout延迟的函数.
0,可能是因为Chrome 0在任何其他事件之前(或至少在重绘事件之前)将事件队列优先级提供给超时.| 归档时间: |
|
| 查看次数: |
7029 次 |
| 最近记录: |