整理AngularJS框架使用过程当中的一些性能优化要(3)

但是这里也有一些权衡,指令不能直接创建一个替换他们父组元素的域。通过隔离的域或Transclusion我们可以创建一个新的对象去跟踪,添加新的监视器,但是这也会降低应用的性能。在添加之前应该仔细想一想有没有这个必要。


10.2 编绎周期

指令(Directive)的compile函数是在域被附加前操作DOM的完美功能(比如说绑定事件)。一个很重要的性能方面是,传入compile函数的元素和属性以原始html模板呈现。只会被运行一次,接下来会直接使用。另外一个重要的点是prelink和postlink的区别。prelink从外向内执行。postlinks从内向外执行。prelink性能稍好一些,因为它不会产生第二次更新周期。但是这时子元素的DOM还未被创建。


11 DOM事件问题

Angular提供了很多预定义的DOM事件指令。ng-click,ng-mouseenter,ng-mouseleave等等。当调用scole.$apply()时这些事件都会被执行。另外一种更有效率的方式是直接在DOM上面绑定addEventListener,并且尽量使用scope.$digest

优化实例


测试一个应用框架确实是个严峻的挑战,当用户点击日志中任何一个单词,我们就要搜索出相关信息,而页面上可以点击的元素又不计其数;我们想让日志的分页功能也瞬间得到反馈。我们其实已经预先获取到了下一页面的日志数据,所以用户接口的更新就成为了瓶颈,如果拿 AngularJS直接实现日志视图的换页功能需要1.2秒,但是如果仔细优化一下的话就可以降到35毫秒。这些优化被证明在应用的其他部分也是适用的,并且对AngularJS适应性也很好。但我们必须打破一些规则来实现我们的想法,稍后讨论。

201635161723160.jpg (590×558)

一个Github更新的日志demo

An AngularJS log viewer

本质上,日志视图就是一个日志消息的列表,每个字都可以点击。所以把Angular的指令加到DOM元素中,简单实现如下:

<span ng-repeat='line in logLinesToShow'> <span ng-repeat='token in line'>{{token | formatToken}} </span> </span>

在单页面应用中有个数千个tokens是很正常的,在早期的测试中,我们发现进入日志的下一页会花费好几秒来执行JavaScript。更糟的是,不相关的操作(比如点击导航下拉框)延迟也不轻,AngularJS的大神说最好把数据元素绑定的数量控制在200以下。对于一个单词就是一个元素的我们来说,早已远超这个数。

分析:

用Chrome的JavaScript profiler工具,我们可以快速定位两个拖延点。首先,每次更新要花大量时间在DOM元素的创建和销毁上,如果新的view有不同的行数,或者任何一行有不同数量单词,Angular的ng-repeat指令就会创建或者销毁DOM元素,这个代价太大了。

其次,每一个单词都有自己的change watcher,AngularJS会watch这些单词,一旦鼠标点击就会触发,这个是影响不相关操作(下拉菜单导航)延迟的罪魁祸首。

优化#1:缓存DOM elements

我们创建了一个ng-repeat指令的变体,在我们的版本中,如果绑定数据的数量减少了,超出的DOM元素会隐藏而不是销毁,如果元素的数量过会儿有增加了,我们会重用这些缓存的元素。

优化#2:Aggregate watchers

用来调用change watchers的所有时间大部分都浪费了,在我们的应用中,特定单词上的数据绑定都是永远不会改变的除非整个日志消息变化,为了达成这一点,我们创建了一个指令”hides“隐藏掉了子元素的change watchers,只有等特定父元素表达式修改的时候才会调用他们。就这样,我们避免了在每一次鼠标点击或者其他微小的修改而导致的全盘change watchers(为了实现这个想法,我们稍微修改了AngularJS的抽象层,我们稍后再细说)。

优化#3:推迟元素创建

前面说了,我们为日志里的每一个单词单独创建了DOM,我们可以利用每一行的单个DOM元素得到相同的视觉呈现;其他元素都是为响应鼠标点操作而创建的,因此,我们决定推迟这部分创建,只有当鼠标移动到某行的时候我们再创建他。

为了实现这个,我们为每一行创建了两个版本,一个就是简单的文本元素来显示完整的日志信息,另外一行就是个占位符,用来显示最终为每一个单词填充后的效果。这个占位符开始是隐藏的,当鼠标移动到那一行的时候才会显示,而简单文本那一行这个时候就隐藏掉。下面会讲到,显示占位符是如何填充单词元素的。

优化#4:避开对隐藏元素的监视

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgyxgz.html