你已经学会了查找和解决问题。希望你的js能正常运行了,但这只是制作帧的一小部分。在这节课里,你将处理样式,也就是像开发工具里标记的那样,重新计算样式。学完这节课后,你将学会从样式计算过程中找到性能问题并学会解决这些问题。请记住,对于我们将要介绍的问题,经常可能是由js触发的,但并不一定是js的问题,在前面我们学习过,样式计算过程将根据DOM确定每个元素的外观属性应该是什么,浏览器获得和DOM很像的渲染树,但只包括需要绘制的元素。
除了考虑元素数量之外,还需要考虑选择器匹配,选择器匹配是只确定某些样式是否应该应用到任何指定DOM元素的过程。
可能会选择这个div包含这样的类或者是这样的更复杂选择器,.b-s:nth-child(3),复杂是因为为了知道样式是否适用它需要弄清楚这个是否是第三个子项。数量少的时候没有问题,但是一旦数量大了,就会有影响。一种非常好的方法是BEM即块(block),元素(element),修饰符(modifier),这是一种编写css的方式,它会对样式元素使用单个类名称,不仅会提供更加模块化,课重复使用,课阅读的样式,并且对性能更优优势。因为对现代浏览器来说,通常类批判是最快的匹配选择器。对于我们刚刚提到的示例,你可以使用这样的类,是一个box即block没有任何元素,而修饰符是three(
.box--three)表示是第三个方框
刚刚解释了复杂的css选择器会如何给浏览器增加工作量,选择器越复杂浏览器就更需要多次在DOM树上上下下移动,次数越多,找到正确元素花费时间就越长,
看http://jsbin.com/gozula/1/quiet这个来找
https://dl.dropboxusercontent.com/u/2272348/codez/udacity/box-recalc-style-slow.html打开这个网址,打开时间轴,按下红色的录制按钮,然后点击“clilke me”按钮,在时间轴重找到Recalculate Style部分,发现self time时间太长,根本达不到60帧/秒,这种情况下,可以采取三种措施,可以减少受影响元素的数量,可以降低选择器的复杂性活或者同时实现二者。
减少受影响元素的数量,意味着减少在渲染树中修改更少的节点,降低选择器复杂度意味着使用更少的标记和类名称来选择选择,但为何不二者都采用呢?这样就双赢了,
https://dl.dropboxusercontent.com/u/2272348/codez/udacity/box-recalc-style-slow.html
性能的提升很明显。
http://output.jsbin.com/aqavin/2/quiet这个网址拖动一下滑条,这一过程需要很长时间,要找出原因,我们需要重新查看下管道,尤其是各个任务的顺序,
顺序很清晰,先执行js,然后执行样式计算,然后执行布局流程,保持这一顺序非常重要,
这段代码问题是使用offsetwidth获取每个元素的宽度,浏览器必须先计算该宽度,这就需要布局,我们来看看这对管道造成的影响,代码将管道布局移到了这里,使布局跑到了样式计算的前方,这并不是问题,除非你更改了样式,而当我们设置段落的宽度时,就更改了样式。
现在陆篮球就要重新完成一遍,这一错误的代价很高。如果你触发了强制同步布局,开发者工具会在这里用感叹号标出来,在帧图表视图中,你会在布局记录的右上角看到红色的三角形。
就会出现强制同步布局,当我们访问某些属性时,就会导致布局流程问题。
(我们称之为布局抖动,也就是快速多次进行强制同步布局)在重新计算样式和布局之间切换,所以这段代码时强制同步布局。第二段代码同样访问offsetHeight导致浏览器运行布局,然后,这里出现了样式更改。这个选项肯定对性能有负面影响。
,然后读取布局属性,这个答案似乎是合理的,因为你先更改了样式,然后读取布局属性,问题在与这个loops,更改样式后,需要运行布局,如果就发生一次,没什么关系。如果在帧结束前,你需要重新计算样式,并再次运行布局则导致浏览器重新执行大量工作,最终导致同步布局。
在js阶段先读取布局属性,意味着你将使用上一帧的布局,然后进行所有样式更改的话,在这个管道中,剩余部分看起来正常,这里关键是批量,所有样式更改将在js之后批量发生,这意味着重新计算样式将在帧结束时发上,并处在管道的正确位置。
然后批量处理所有的样式更改,这个一个非常简单的修正方法,但是可以大大提高性能。