即使没有任何变化,触摸 DOM 是否会触发回流和重绘?
Does touching the DOM trigger a reflow and repaint even if nothing changes?
我正在开发一个小型 JavaScript 模板引擎,我有两种可能的方法来处理模型更改时对 DOM 的更新:
检查 DOM 更新是否真的需要再做。这样做的好处是不会冒不必要的更新风险,但我在跟踪旧值上浪费了 space。
if (oldValue !== newValue) {
element.textContent = newValue;
}
就去做吧。这样显然更简单了,但是我怕无缘无故触发重绘回流
element.textContent = newValue;
请注意,我还通过调用 setAttribute
、addClass
和 removeClass
以及设置 style[prop] = value
.
来操纵 DOM
所以,我的问题是:现代浏览器是否足够聪明,可以注意到实际上没有任何更改,因此如果您触摸 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>
- 在Chrome55,只有
setAttribute()
和jQuerytext()
触发了Dom Change
事件。
- 在 Firefox 50 中,一切都会触发
Dom Change
事件。
- 在 Edge 38 中,一切都触发了
Dom Change
事件。
我正在开发一个小型 JavaScript 模板引擎,我有两种可能的方法来处理模型更改时对 DOM 的更新:
检查 DOM 更新是否真的需要再做。这样做的好处是不会冒不必要的更新风险,但我在跟踪旧值上浪费了 space。
if (oldValue !== newValue) { element.textContent = newValue; }
就去做吧。这样显然更简单了,但是我怕无缘无故触发重绘回流
element.textContent = newValue;
请注意,我还通过调用 setAttribute
、addClass
和 removeClass
以及设置 style[prop] = value
.
所以,我的问题是:现代浏览器是否足够聪明,可以注意到实际上没有任何更改,因此如果您触摸 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>
- 在Chrome55,只有
setAttribute()
和jQuerytext()
触发了Dom Change
事件。 - 在 Firefox 50 中,一切都会触发
Dom Change
事件。 - 在 Edge 38 中,一切都触发了
Dom Change
事件。