所以我有一个我正在写的Polymer应用程序。我已经为装载覆盖层编写了一个非聚合物网络组件,我可以在加载聚合物时以及当应用程序Websocket连接/重新连接时显示。
以下是一些我必须说明我正在做什么的CSS:
.overlay {
background: #000;
bottom: 0;
height: 100%;
left: 0;
opacity: 0;
pointer-events: none;
position: fixed;
right: 0;
transition: opacity 0.2s;
top: 0;
width: 100%;
z-index: 9999999;
}
.overlay[opened] {
opacity: 0.8;
pointer-events: auto;
}
.loader {
display: none;
}
.overlay[opened] .loader {
display: block;
}
现在这个叠加层和我所拥有的基于CSS的加载器动画仅在我真实地加载应用程序时使用,但是如果WebSocket断开连接也会显示它。
我的问题是,出于性能原因,我应该完全从DOM中删除元素并在需要时将其添加回来吗?叠加在不使用时是否完全透明,隐藏加载器动画是否意味着它们对绘图性能没有影响?
注意:我希望尽可能避免“不要微观优化”的答案;)
答案 0 :(得分:2)
<强> TL; DR:强>
通常,渲染元素会影响页面性能,当对其进行更改会触发DOM中后续元素的重绘或者在其父级上触发resize
时,因为resize
会因此而变得昂贵最高可达100次/秒,具体取决于设备。
只要对元素的更改不会在DOM树中的后续元素上触发重绘,就会将其渲染,隐藏在某个不透明元素后面(或在内容上方,opacity:0
和{{1}之间并且根本没有显示它是微不足道的。
元素 的更改不会触发除自身 之外的任何内容的重绘,因为它具有pointer-events:none
。如果它具有position:fixed
或者对它的更改将通过不会在后续兄弟节点上触发重绘的属性(例如position:absolute
和transform
)进行更改,则情况也是如此。
除非加载器在渲染引擎上非常繁重(很少出现这种情况) - 想想带有3d场景,材质和灯光映射的WebGL加载器 - 在这种情况下,最好不向用户显示时不显示它,差异将是如此之小,真正的挑战是衡量这种差异,性能明智。
事实上,如果对其进行渲染并且仅更改其opacity
和opacity
属性并不总是比切换其pointer-events
属性更便宜,我不会感到惊讶,因为每次打开/关闭浏览器时,浏览器都不必从DOM中添加/删除它。但是,真正的问题是:我们如何衡量它?
编辑:实际上,我制作了一个小型测试工具,有10k模态。我在Chrome上的Linux上获得了以下结果:
display
...所以我的假设是正确的:`opacity` average: 110.71340000000076ms | count: 100
`display` average: 155.47145000000017ms | count: 100
整体来说更贵。
display
更改大多数在opacity
左右,除了少数例外,而110ms
更改在删除节点时更快,但在添加时更慢。
随意在不同的浏览器中,在不同的系统上自行测试:
display
$(window).on('load', function () {
let displayAvg = 0, displayCount = 0,
opacityAvg = 0, opacityCount = 0;
for (let i = 0; i < 10000; i++) {
$('body').append($('<div />', {
class: 'modal',
html:'10k × modal instances'
}))
}
$(document)
.on('click', '#display', function () {
$('.modal').removeClass('opacity');
let t0 = performance.now();
$('.modal').toggleClass('display');
setTimeout(function () {
let t1 = performance.now();
displayAvg += (t1 - t0);
console.log(
'`display` toggle took ' +
(t1 - t0) +
'ms \n`display` average: ' +
(displayAvg / ++displayCount) +
'ms | count: ' +
displayCount
);
})
})
.on('click', '#opacity', function () {
$('.modal').removeClass('display');
let t0 = performance.now();
$('.modal').toggleClass('opacity');
setTimeout(function () {
let t1 = performance.now();
opacityAvg += (t1 - t0);
console.log(
'`opacity` + `pointer-events` toggle took ' +
(t1 - t0) +
'ms \n`opacity` average: ' +
(opacityAvg / ++opacityCount) +
'ms | count: ' +
opacityCount
);
});
})
});
body {
margin: 0;
}
.buttons-wrapper {
position: relative;
z-index: 1;
margin-top: 3rem;
}
.modal {
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
padding: 1rem;
}
.modal.display {
display: none;
}
.modal.opacity {
opacity: 0;
pointer-events: none;
}
.as-console-wrapper {
z-index: 2;
}
但这个平均值是10k元素。将它除以10k,它几乎没有任何区别:我们的谈话时间不到0.45%。
答案 1 :(得分:0)
如果元素具有'Animation'属性进行动画处理且其持续时间是无限的,浏览器将不断重绘网站,这将影响网站性能并降低FPS。
但是隐藏具有诸如 Opacity:0; 之类的属性的元素不会成功,因为元素仍在CSSOM渲染树队列中。
Visibility:hidden; 和 display:none; 应该可以做到这一点,因为CSSOM构造浏览器不会呈现诸如 display:none之类的隐藏元素;和可见性:隐藏