浏览器是根据更改重新渲染整个页面还是仅重新渲染特定元素?

Posted

技术标签:

【中文标题】浏览器是根据更改重新渲染整个页面还是仅重新渲染特定元素?【英文标题】:Does the browser re-render the whole page on changes or only the specific elements? 【发布时间】:2014-10-17 08:46:37 【问题描述】:

假设我有一个 id 为 #msg 的元素,并且在某种情况下我想向它添加一个类以应用样式,例如使文本显示为红色。 我可以做到$('#msg').addClass(theclass) 我的问题是浏览器如何反应?它是重新渲染整个页面还是重新渲染特定元素?

【问题讨论】:

答案取决于浏览器、版本(可能是平台)、新类隐含的css更改、祖先节点和元素周围节点的css。例如,如果你想对 Chrome 做一些优化,你可以看看 布局边界 @Volune:我很难相信没有指定。从我的角度来看,这会极大地影响页面的性能。 我不明白你是如何从重新渲染显着影响性能必须指定重新渲染。指定页面的显示。如果您更改课程,规范会告诉您更改后的显示内容。然后,您可以确定需要重新渲染的内容。默认算法是重绘所有页面,然后与之前的显示进行比较。浏览器的开发人员仍在不断改进算法来找到需要重新渲染的内容,而无需重新绘制所有页面。 @Jim 这个问题解决了吗?当用户寻求帮助阅读这些帖子时,未答复的帖子会减慢速度,请选择一个帖子作为答案或重新访问并更新此帖子。 【参考方案1】:

对于您的示例 (addClass),这取决于您添加的类中的内容。添加类本身只会修改目标节点上的属性。

某些更改会导致重绘,即在更改颜色、bgcolor 等时。只有应用了新 CSS 的元素才会重新渲染。 某些更改会导致重排,即元素或它们的内容所占据的可见空间改变尺寸或位置。取决于他们自己的,他们的父母和孩子的属性,以及那些父母和孩子的属性,等等等等,回流会影响文档树中的更多元素。

浏览器足够聪明,只修改需要重新渲染的元素。最小化重新渲染数量的一种技术是设置元素的 position: absolutedisplay: none 以将其暂时从文档流中删除,进行更改,然后重新插入。这一点尤其重要,例如。你让一些元素向下滑动。如果元素在流中且位于 DOM 树的开头,则它拉伸的每个像素都会导致重新渲染。

为了好玩,让我们用桌子上的纸做一个简单的类比,在这个例子中插入元素。桌子是您的浏览器窗口, = 纸张,_ = 空白空间。您想将另一张纸放在最左上角的位置。这是开始的情况:

□ □ □ □□ □ □ □_ _ _ _

将新床单放在桌子上后:(■ = 新,▧ = 已移动)

■ □ □ □▧ □ □ □▧ _ _ _

如果第二行是一长卷纸(= 全角 div),则整行都会移动:

■ □ □ □▧ _ _ _▧▧▧▧▧▧▧

但是,如果您在第三行插入工作表,则不会发生回流。

注意:这是理论上的解释。其效率因浏览器而异。来源:高性能 javascript,“重绘和重排”,第 70 页。

【讨论】:

【参考方案2】:

我的理解是,根据这个工具https://developer.chrome.com/devtools/docs/timeline 提供的结果,NO,整个 DOM 没有被重新绘制/重新生成,只是改变了类的元素。

Demo

html

<p>Lorem ipsum dolar sit amet...</p>

<input id="btn" type="button" value="click me" />

Javascript:

$(document).on('click', '#btn', function ()  
  $('p').addClass('red')  
)

CSS:

.red 
    color: red;

****编辑**** 我不得不将答案从“否”改为“是”,然后从“是”改回“否”。此工具清楚地指出正在重新绘制的相关元素,其他 DOM 元素不受影响。

但是 如果元素内/外维度发生变化,甚至需要通过javascript进行查询,这就需要重新绘制DOM元素,并重新绘制整个元素分支,然后被浏览器缓存。

【讨论】:

尝试使用内联元素,看看其他元素可能需要重绘,例如:&lt;span&gt;A&lt;/span&gt;&lt;span id="putAClassThatChangeTheFontSize"&gt;B&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;

以上是关于浏览器是根据更改重新渲染整个页面还是仅重新渲染特定元素?的主要内容,如果未能解决你的问题,请参考以下文章

Vue中重新渲染组件的方法总结

Ember:模型更改时重新渲染路线的模板

vue 监听窗口变化对页面部分元素重新渲染

使用 LWJGL 对 GUI 进行部分渲染 [关闭]

如何使用AngularJS重新加载或渲染整个页面

如果子组件发生更改,如何重新渲染父组件