javascript - 即使没有任何变化,触摸 DOM 是否会触发回流和重绘?

标签 javascript html performance dom reflow

我正在开发一个小型 JavaScript 模板引擎,我有两种可能的方法来处理模型更改时对 DOM 的更新:

  1. 在执行之前检查是否真的需要 DOM 更新。这样做的好处是不会冒不必要的更新风险,但我在跟踪旧值上浪费了空间。

    if (oldValue !== newValue) {
        element.textContent = newValue;
    }
    
  2. 就去做吧。这显然更简单,但我担心我会无缘无故地触发重绘和回流。

    element.textContent = newValue;
    

请注意,我还通过调用 setAttributeaddClassremoveClass 以及设置 style[prop] =值

所以,我的问题是:现代浏览器是否足够聪明,可以注意到实际上没有任何更改,因此如果您在没有实际更改任何内容的情况下触摸 DOM,则不会运行回流或重绘?

最佳答案

使用 MutationObserver api您可以检测到 DOM 更改。

这是一个示例,您可以根据需要查看浏览器是否触发了 Dom Changed 事件。

这里有 jquery 的 text('...')el.textContent(不使用 jquery)。

$(document).ready(function() {
  $('#btn1').click(function() {
    console.log('text changed - jquery');
    $('#a1').text('text 1');
  });
  $('#btn2').click(function() {
    console.log('text changed - textContent');
    $('#a1')[0].textContent  = $('#a1')[0].textContent 
  });
  $('#btn3').click(function() {
    console.log('class changed');
    $('#a1').attr('class', 'cls' + Math.floor(Math.random() * 10));
  });
});


var target = $('#a1')[0];

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  var changed = false;
  mutations.forEach(function(mutation) {
    // You can check the actual changes here
  });
  console.log('Dom Changed');
});

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);
.cls1 {
  border: 1px solid red;
}
.cls2 {
  border: 1px solid pink;
}
.cls3 {
  border: 1px solid cyan;
}
.cls4 {
  border: 1px solid darkgreen;
}
.cls5 {
  border: 1px solid orange;
}
.cls6 {
  border: 1px solid darkred;
}
.cls7 {
  border: 1px solid black;
}
.cls8 {
  border: 1px solid yellow;
}
.cls9 {
  border: 1px solid blue;
}
.cls10 {
  border: 1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1" class="cls1">text 1</div>
<button id="btn1">Change text - jquery (keep original)</button><br />
<button id="btn2">Change text - textContent (keep original)</button><br />
<button id="btn3">Change class (real change)</button>

  • 在 Chrome 55 中,只有 setAttribute() 和 jQuery text() 触发了 Dom Change 事件。
  • 在 Firefox 50 中,一切都会触发 Dom Change 事件。
  • 在 Edge 38 中,一切都触发了 Dom Change 事件。

关于javascript - 即使没有任何变化,触摸 DOM 是否会触发回流和重绘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41453465/

相关文章:

css - 设置 Font Awesome 图标位置

html - 100% 宽度水平折叠?

c# - 避免 VBCSCompiler 性能命中 Roslyn 支持的 ASP.NET Razor MVC View ?

javascript - 将 div id 动态设置为变量并在 jquery 中将其用于悬停

javascript - 通知 Promise Angular 删除回调

javascript - highchart 未显示在 django 推特 Bootstrap 中

html - 浏览器之间的视觉差异

java - 引用游标和直接 Java 代码之间的性能差异

JavaScript:比较字符时使用 charCode 有好处吗?

javascript - 确定 rar 文件是否受密码保护