AngularJS监听计数

大家都知道,AngularJS双向数据绑定很Cool。简单地说,Angular在scope模型上设置了一个监听队列,用来监听数据变化并更新view 。每次绑定一个东西到View上时AngularJS就会往$watch队列里插入一条$watch,用来检测它监听的model里是否有变化的东西。当浏览器接收到可以被Angular执行环境处理的事件时,就会触发$digest循环,遍历所有的$watch,model稳定后结束循环。大多数时候,浏览器速度很快这个过程不长,这不是一个大问题。但如果在很复杂的应用下使用不当会造成性能问题,比如说表格树组件中滥用双向数据绑定很容易造成界面很卡。

Angular为每个$digest循环添加了一个监听:

{{expression}} – 在您的模板(以及其他任何有表达式的地方)
$scope.$ watch(’expression / function’) – 在你的JavaScript中

监听计数

Batarang等插件已经有监听计数功能,不过我觉得它们这个功能好像不准确。下面这个简单的脚本将帮助您识别应用的绝了大部分监听:

function getWatchers(root) {
  root = angular.element(root || document.documentElement);
  var watcherCount = 0;
 
  function getElemWatchers(element) {
    var isolateWatchers = getWatchersFromScope(element.data().$isolateScope);
    var scopeWatchers = getWatchersFromScope(element.data().$scope);
    var watchers = scopeWatchers.concat(isolateWatchers);
    angular.forEach(element.children(), function (childElement) {
      watchers = watchers.concat(getElemWatchers(angular.element(childElement)));
    });
    return watchers;
  }
  
  function getWatchersFromScope(scope) {
    if (scope) {
      return scope.$$watchers || [];
    } else {
      return [];
    }
  }
 
  return getElemWatchers(root);
}
getWatchers().length

只需将其粘贴到您的控制台(或使用Chrome浏览器片段)并如下使用:

//在整个页面上获取所有监听
getWatchers();

//获取特定元素(及其子元素)的
监听getWatchers(document.body);

//在Chrome开发工具中选择感兴趣的元素
getWatchers($ 0);

它会返回你给出的元素及其所有子元素的监听。

减少你的监听数量

幸运的是,AngularJS 1.3以后增加一次性绑定操作符::,这样可以减少模板中的监听数量。如果你只能使用低版本的AngularJS中,那么好有两个替代解决方案(angular-once或者bindonce),可以很好地减少你的监听数量。

发表评论

电子邮件地址不会被公开。 必填项已用*标注