AngularJS Debugging

当我们在构建一个大型的Angular应用时,经常会遭遇一些很棘手的问题,而且看起来很难排查和解决。

借助DOM进行调试

虽然这并不是必需的步骤,但我们可以访问DOM元素上附加的Angular属性。通过这些属性窥探数据在我们的应用中是如何流向的。

我们不应该在应用程序的生命周期内依靠DOM元素获取元素的属性。我们也只是出于调试的目的才使用这种方式。

为了从DOM获取这些属性,我们需要找到我们感兴趣的DOM元素。如果引入了完整的jQuery库,就可以使用jQuery的选择器语法:$("selector")

当然对于从DOM中定位和获取元素而言,我们不应该依赖jQuery。此外我们还可以使用document.querySelector()方法。

需要注意的是document.querySelector()方法并非所有浏览器都支持,并且只适合并不复杂的元素选择器,而Sizzle(jQuery所用的选择器库)或者jQuery都支持更为复杂的选择器。

我们可以通过选择ngApp指令所在的元素来获取$rootScope,还可以使用angular.element()方法将其封装为一个Angular的元素。

封装为Angular元素之后,我们就可以调用众多的方法来从DOM内部检查我们的Angular应用了。这么做之前,我们首先要从DOM中选择元素。使用纯粹的JavaScript和Angular,我们可以这样做:

var rootEle = document.querySelector("html");
var ele = angular.element(rootEle);

通过这个元素,我们就可以获取我们应用程序的各个部分。

scope()

我们可以通过使用元素上的scope()方法从该元素(或者它的父元素)获取$scope

var scope = ele.scope();

借助元素的作用域,我们可以分析任何作用域上的属性,比如我们在控制器中给作用域设置的自定义变量。我们还可以窥探到元素的$id,它的$parent对象,元素上设置的$watchers,甚至还可以手动遍历作用域链。

controller()

我们可以通过controller()方法获取当前元素(或者其父元素)的控制器:

var ctrl = ele.controller();
// or
var ctrl = ele.controller('ngModel');

injector()

我们还可以使用所选元素上的injector()方法获取当前元素(或者包含的元素)上的注入对象。

var injector = ele.injector();

通过这个注入对象,我们就可以实例化我们应用内部的任何Angular对象,诸如services,其它的controllers,或者任何其它对象。

inheritedData()

我们可以通过元素上的inheritedData()方法很容易的获取到当前元素$scope所关联的数据对象:

ele.inheritedData();

Angular的该inheritedData()方法会遍历DOM从而向作用域链的上游查找,直到找到特定的值或者到达作用域链的顶端。

如果你在使用Chrome作为开发工具,我们可以通过开发者工具更快捷的找到感兴趣的元素,只需要在浏览器上右键选择要检查的元素。在控制台中,元素自身会以变量$0存储,我们就可以通过调用angular.element($0)来获取Angular封装后的元素。

Debugger

Google Chrome拥有自己的调试工具可以代码中插入断点。debugger语句会导致浏览器在执行过程中中断,并使得我们可以在浏览器中执行的实际应用内部检查断点处执行的代码。

要使用debugger,我们只需要在应用程序的上下文代码中添加一行代码即可:

angular.module('myApp', [])
.factory('SessionService', function($q, $http) {
  var service = {
    user_id: null,
    getCurrentUser: function() {
      debugger; // Set the debugger inside 
                // this function
      return service.user_id;
    }
  }
  return service;
});

在该服务中,我们调用了debugger;方法来有效地_冻结_了我们的应用程序。

只要在浏览器中打开Chrome的开发者工具,我们就能在当前应用程序代码执行的断点处使用console.log()和其他的JavaScript命令来进行调试和输出了。

当我们完成应用程序代码的调试后,我们需要确保移除这行代码,因为它会冻结浏览器,即使在生产环境中亦是如此。

Angular Batarang

Angular Batarang是一个由Google Angular团队所开发的Chrome插件,它作为一个调试工具能够很好地同Angular应用集成。

安装Batarang

要安装Batarang,只需要从Chrome的Web商店或者Github仓库(https://github.com/angular/angularjs-batarang)上下载安装即可。

安装完成成后,我们就可以在开发者工具中看到新增加的AngularJS的面板,然后点击enable就可以开启Batarang进行当前页面调试信息的收集了。

通过Batarang我们可以查看Angular应用的作用域链,性能,依赖关系,和其它关键指标。

检查Models

当我们开启Batarang之后,页面会重载,之后可以看到多出一个面板可以查看当前页面上不同的作用域。

我们可以通过点击+按钮选择一个作用域,找到我们感兴趣的元素然后点击即可。

当使用检查器选择一个作用域之后,我们就可以看到当前作用域元素上所有的属性和它们的当前值。

检查性能

我们还可以使用Batarang的性能标签来窥探当前应用程序的性能。

在性能面板中,我们可以窥探到应用程序在不同作用域中的watch列表以及每个表达式所耗费的时间,时间分别包含绝对时间和相对整个应用程序而言的百分比。

查看依赖关系图表

Batarang工具还有一个很棒的功能就是能够将依赖关系可视化为图表展示出来。我们可以查看当前应用程序的依赖关系并且能够看到当前应用依赖的不同库,从而能够跟踪到哪些库根本没有被应用依赖到。

将应用可视化

通过Batarang可以深度查看当前页面上的应用。使用Options选项卡,我们可以查看:

应用

当前页面上的不同应用程序(使用ngApp指令)。

绑定

绑定是在视图中设置的,通过ng-bind或者通过模板标签``包裹的元素。

作用域

我们还可以定位和深度查看视图中的作用域。

Options面板还可以查看当前应用所用Angular的版本号,以及我们是否使用了CDN。

其它Angular应用的调试工具

也是一个浏览器的AngularJS检查器,它也是作为Chrome或者Safari插件的形式存在,可以用来对Angular应用进行开发和调试。其功能与Batarang类似。