Javascript 隐藏/透明元素是否会影响渲染性能?
所以我有一个聚合物应用程序,我正在写。我已经为加载覆盖编写了一个非聚合物web组件,我可以在聚合物加载和应用程序Websocket连接/重新连接时显示该组件 下面是一些CSS的示例,我必须给出我正在做的事情:Javascript 隐藏/透明元素是否会影响渲染性能?,javascript,html,css,web-component,Javascript,Html,Css,Web Component,所以我有一个聚合物应用程序,我正在写。我已经为加载覆盖编写了一个非聚合物web组件,我可以在聚合物加载和应用程序Websocket连接/重新连接时显示该组件 下面是一些CSS的示例,我必须给出我正在做的事情: .overlay { background: #000; bottom: 0; height: 100%; left: 0; opacity: 0; pointer-events: none; position: fixed;
.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中删除元素,并在需要时重新添加它?覆盖在不使用时是完全透明的,并且加载程序动画是隐藏的,这是否意味着它们对绘图性能没有影响
注意:如果可能的话,我希望避免使用“不进行微观优化”的答案;) TL;医生: 一般来说,当对呈现元素的更改触发DOM中后续元素的重新绘制或在其父元素上触发
resize
时,呈现元素会影响页面性能,因为resize
触发100次/秒(取决于设备)可能代价高昂
只要对元素的更改不会触发对DOM树中后续元素的重新绘制,将其渲染、隐藏在某个不透明元素后面(或隐藏在内容上方,具有
不透明度:0
和指针事件:无
)和完全不显示之间的差异就无关紧要了
对元素的更改不会触发对除自身以外的任何对象的重新绘制,因为它具有位置:固定的。如果它有position:absolute
,或者通过不触发后续同级重新绘制的属性(如transform
和opacity
)对其进行更改,则情况也是如此
除非加载程序在渲染引擎上真的很繁重(这种情况很少出现——想想带有3d场景、材质和灯光贴图的WebGL加载程序——在这种情况下,最好不要在不向用户显示的情况下显示),否则差异将非常小,真正的挑战是从性能角度衡量这种差异
事实上,如果对其进行渲染,并且仅更改其不透明度
和指针事件
属性,总的来说并不比切换其显示
属性便宜,我也不会感到惊讶,因为浏览器不必在每次打开/关闭时从DOM中添加/删除它。但是,真正的问题是:我们如何衡量它
编辑:实际上,我制作了一个小型测试工具,包含10k模态。在Chrome中,我在Linux上获得了以下结果:
`opacity` average: 110.71340000000076ms | count: 100
`display` average: 155.47145000000017ms | count: 100
。。。所以我的假设是正确的:显示
总体上更昂贵
不透明度
的变化大多在110ms左右,很少有例外,而显示
的变化在删除节点时更快,但在添加节点时更慢
您可以在不同的浏览器、不同的系统上自行测试:
$(窗口).on('load',函数(){
让displayAvg=0,displayCount=0,
opacityAvg=0,opacityCount=0;
for(设i=0;i<10000;i++){
$('body')。追加($(''){
类别:'模态',
html:“10k×;模态实例”
}))
}
$(文件)
.on('单击','显示',函数(){
$('.modal').removeClass('opacity');
设t0=performance.now();
$('.modal').toggleClass('display');
setTimeout(函数(){
设t1=performance.now();
显示平均值+=(t1-t0);
console.log(
“`display`toggle take'+
(t1-t0)+
'ms\n'display'平均值:'+
(displayAvg/++displayCount)+
“小姐|伯爵:”+
显示计数
);
})
})
.on('click','#opacity',函数(){
$('.modal').removeClass('display');
设t0=performance.now();
$('.modal').toggleClass('opacity');
setTimeout(函数(){
设t1=performance.now();
opacityAvg+=(t1-t0);
console.log(
“`opacity`+`指针事件`toggle take'+
(t1-t0)+
'ms\n'opacity`平均值:'+
(opacityAvg/++opacityCount)+
“小姐|伯爵:”+
不透明计数
);
});
})
});代码>
正文{
保证金:0;
}
.按钮包装{
位置:相对位置;
z指数:1;
边缘顶部:3rem;
}
.莫代尔{
高度:100vh;
宽度:100vw;
位置:固定;
排名:0;
左:0;
填充:1rem;
}
.模态显示{
显示:无;
}
.模态不透明度{
不透明度:0;
指针事件:无;
}
.作为控制台包装{
z指数:2;
}
切换“显示”
切换`opacity`+`指针事件`
如果元素使用'Animation'属性设置动画,并且其持续时间为无限长,则浏览器将持续重新绘制站点,这将影响站点性能并降低FPS
但是,隐藏具有以下属性的元素:0
将不起作用,因为元素仍在CSSOM渲染树队列中
可见性:隐藏和显示:无应该基于CSSOM构造来实现这一点,浏览器不会渲染隐藏元素,例如display:none;&可见性:隐藏您可以添加显示:无将其从渲染树中删除,而不是从DOM中删除。如果它是透明的,我相信它仍然在渲染树中。@keja,我对它很好奇,并制作了一个测试工具。显然,从DOM中添加/删除比仅仅更改
不透明度
和指针事件
更昂贵。“不过,我们所说的ms不到1%,所以,事实上,它无关紧要。”AndreiGheorghiu补充道,页面的其余部分呈现速度比我想象的要快