我想为一个JavaScript函数编写一个单元测试,并测量函数在浏览器中触发流的频率。给定以下示例:
// Bad example
function foo(elements) {
for (var i = 0; i < elements.length; i++) {
elements[i].className = 'w' + elements[i].offsetWidth;
}
}
// Good example
function foo(elements) {
var widths = [];
for (var i = 0; i < elements.length; i++) {
widths[i] = elements[i].offsetWidth;
}
for (i = 0; i < elements.length; i++) {
elements[i].className = 'w' + widths[i];
}
}
对于第一个例子,单元测试应该失败,因为它触发了每个元素的回流,但对于第二个例子,应该通过,因为它没有触发回流。
唯一接近我想要的是mozPaintCount
,但它只对每次油漆递增,而不是每次回流。我需要mozReflowCount
或mozRecalculateStyleCount
之类的东西,但我没有在任何浏览器中找到任何可能的东西。如果存在这样的属性,则单元测试可能如下所示:
// mozReflowCount doesn’t exist, such a property is what I’m looking for
var reflowCountBefore = window.mozReflowCount;
foo(document.querySelectorAll('*'));
if (reflowCountBefore === window.mozReflowCount) {
// passed
}
else {
// failed
}
我知道我可以查看浏览器的开发工具,手动检查触发了多少回流或"强制同步布局",但我不知道如何从JavaScript单元测试中访问这些数据。
问:我如何计数回流在浏览器通过JavaScript?
最好的方法可能是使用MutationObserver: MutationObserver API
那一页的例子给出了一个很好的关于如何实现它的概要:
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// 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);
// later, you can stop observing
observer.disconnect();