通过增加和移除元素,修改属性,类或者听过动画的方式来修改DOM都会导致浏览器重新计算元素的样式,且在大多是情况下重新布局页面亦或重新布局部分页面。这个过程被叫做computed style calculation。
- 减少选择器的复杂性
- 减少样式必须被计算的元素的个数
计算样式的一部分是创建一系列匹配的选择器,本质上是浏览器计算出什么类,伪选择器和ID应用到指定的元素上。
第二部分包括从匹配的选择器上使用样式的规则且计算出元素最终拥有的样式。在Blink(Chrome和Opera渲染引擎)中,这些过程消耗都是基本上相等的。
大约50%的时间用于为元素计算和选择器匹配的元素的样式。另一部分的时间用于从匹配的样式规则中,构建并且渲染样式。
减少选择器的复杂性
在最简单的例子中,你的元素只有一个属性:
.title { /* styles */ }
当你的项目越来越复杂,你的选择器也将也来越复杂,可能如下:
.box:nth-last-child(-n+1) .title { /* styles */ }
为了知道样式运用在哪里,浏览器会这样询问:“这里有一个元素是title类,且它的父元素刚好是一个box类的元素的第-n+1个子元素?”
计算出这个元素将花费很长的时间,所以你可以很简单的为上面复杂的选择器替换成一个类名:
.final-box-title { /* styles */ }
你可能会有类名命名问题,但是对浏览器而言工作简单多了!
如果你想要指定类中的最后一个元素,浏览器必须要知道整个类,还有知道类元素之间的顺序,类中的每个元素是第几个nth-last-child,这将给浏览器带来巨大的工作,所以我们可以简单的为要寻找的元素添加一个选择器名就可(例如添加一个类名)。
减少将会被设置样式的元素数量Reduce the number of elements being styled
比样式跟新更加重要的影响性能的因素是当元素修改的时候浏览器的工作量。
通常而言,需计算样式的元素的数量等于元素数量乘以选择器个数,因为每一个元素都需要至少都要检查每个样式来看看元素是否和样式匹配。
对于旧的浏览器而言,如果你修改了其中的一个元素的样式,将会作用于整个页面,检查页面上的所有元素是否默认被修改。但是现代的浏览器不会这样,现代的浏览器只会在指定的元素上做样式的计算。
所以,为了兼容所有浏览器的性能,你应该减少无效元素的数量。
你要记住的,越小的拥有越少规则的树执行速度要比越大的亦或越复杂的规则要快的多。
估量你样式重新计算所需要的耗费
最简单且最好的计量样式损耗的方式是使用谷歌浏览器开发者工具中的时间轴模块(Timeline):
最上面的条状图解释了每一帧的情况,如果你看见条比最低的线,也就是60fps要低的话,这说明该帧运行时间较长。
如果你在一些交互(例如scroll)中有运行时间较长的帧,那么你考考虑对其进行优化。
如果你有一个很大的紫色阻塞,就像上面展示的一样,点击它,将会展示更详细的信息,如下:
上面展示了一个运行时间很长的样式重新计算时间,他耗费了18ms以上,且发生在scroll事件中间,对用户体验影响巨大。
如果你点击时间,你将会得到一个call stack,指示了你js代码中哪一部分应该对这个样式的修改负责。
同样,你还可以获得样式修改时影响的元素个数(上面是406个),你也可以知道样式计算耗时。
使用BEM原则
BEM (Block, Element, Modifier) 原则就是为每一个元素命名,当你需要使用继承机制的时候,你应该直接使用元素名,元素名的命名上可以体现继承规则:
.list { } .list__list-item { }
如果你要元素的最后一个子元素,你可以这样:
.list__list-item--last-child {}
使用BEM原则可以有很好的性能,并且命名上易懂,如果你使用继承机制来选择元素的话,注意你的损耗将会是巨大的,因为你讲遍历指定元素的父元素亦或子元素。