AngularJS 开发者最常犯的 10 个错误(3)

正如上文中提到的,在外部AngularJS是很不错的。因为在一个循环消化中需要进行dirty检查,一旦watcher的数目超过2,000,循环会出现很明显的问题。(2,000仅是一个参考数,在1.3版本中AngularJS对循环消化有更为严谨的控制,关于这个Aaron Graye有较为详细的叙述)

这个IIFE(快速响应函数)可输出当前本页中的watcher的数目,只需将其复制到console即可查看详情。IIFE的来源跟Jared关于StackOverflow的回答是类似的。

(function () {
    var root = $(document.getElementsByTagName('body'));
    var watchers = [];
 
    var f = function (element) {
        if (element.data().hasOwnProperty('$scope')) {
            angular.forEach(element.data().$scope.$$watchers, function (watcher) {
                watchers.push(watcher);
            });
        }
 
        angular.forEach(element.children(), function (childElement) {
            f($(childElement));
        });
    };
 
    f(root);
 
    console.log(watchers.length);})();

使用这个,可以从Batarang的效率方面来决定watcher及watch tree的数目,可以看到在哪些地方顾在或哪些地方没有改变的数据有一个watch。

当有数据没有变化时,但在Angular中又想让它成为模板,可以考虑使用bindonce.Bindonce在Angular中仅是一个可能使用模板的指令,但没有增加watch的数目。

8 审视$scope

Javascript的基于原型的继承和基于类的继承在一些细微的方面是不同的。通常这不是问题,但是差别往往会在使用$scope时出现。在AngularJS中每一个$scope都从它的父$scope继承过来,最高层是$rootScope。($scope在指令中表现的有些不同,指令中的隔离作用域仅继承那些显式声明的属性。)

从父级那里分享数据对于原型继承来说并不重要。不过如果不小心的话,会遮蔽父级$scope的属性。

我们想在导航栏上呈现一个用户名,然后进入登陆表单。

<div ng-controller="navCtrl">
  <span>{{user}}</span>
  <div ng-controller="loginCtrl">
        <span>{{user}}</span>
        <input ng-model="user"></input>
  </div></div>

考你下:当用户在设置了ngModel的文本框中输入了值,哪个模板会被更新?是navCtrl,loginCtrl还是两者?

如果你选loginCtrl,那么你可能对原型继承的机理比较了解了。当寻找字面值时,原型链并没有被涉及。如果navCtrl要被更新的话,那么查找原型链是必要的。当一个值时对象的时候就会发生这些。(记住在Javascript中,函数、数组合对象都算作对象)

所以想要获得期望的效果就需要在navCtrl上创建一个对象可以被loginCtrl引用。

<div ng-controller="navCtrl">
  <span>{{user.name}}</span>
  <div ng-controller="loginCtrl">
        <span>{{user.name}}</span>
        <input ng-model="user.name"></input>
  </div></div>

现在既然user是一个对象了,原型链会被考虑进去,navCtrl的模板和$scope也会随着loginCtrl更新。

这可能看上去像一个设计好的例子,但当涉及到像ngRepeat那样会创建子$scope的时候问题就会出现。

9 手工测试

虽然测试驱动开发可能不是每一个开发者都喜欢的开发方式,不过每次开发者去检查他们的代码是否工作或开始砸东西时,他们正在做手工测试。

没有理由不去测试一个AngularJS应用。AngularJS从一开始就是被设计地易于测试的。依赖注入和ngMock模块就是证据。核心团队开发了一些工具来讲测试带到另一个级别。

9.1 Protractor 

单元测试是一组测试集的基本元素,但随着应用复杂性的提高,集成测试会引出更多实际问题。幸运地是AngularJS核心团队提供了必要的工具。

“我们构建了Protractor,一个端对端的测试运行工具,模拟用户交互,帮助你验证你的Angular应用的运行状况。”

Protractor使用Jasmine测试框架来定义测试。Protractor为不同的页面交互提供一套健壮的API。

有其他的端对端工具,不过Protractor有着自己的优势,它知道怎么和AngularJS的代码一起运行,特别是面临$digest循环的时候。 

9.2 Karma

一旦使用Protractor写好了集成测试,测试需要被运行起来。等待测试运行特别是集成测试,会让开发者感到沮丧。AngularJS核心团队也感到了这个痛苦并开发了Karma

Karma是一个Javascript测试运行工具,可以帮助你关闭反馈循环。Karma可以在特定的文件被修改时运行测试,它也可以在不同的浏览器上并行测试。不同的设备可以指向Karma服务器来覆盖实际场景。

10 jQuery的使用

jQuery 是个很不错的类库. 它将跨平台开发标准化. 在现代网页开发中具有很重要的地位. 虽然 jQuery 拥有许多强大的功能. 但是他的设计理念却与 AngularJS 大相径庭.

AngularJS 是用来开发应用框架的; jQuery 则是一个用来简化 HTML 文档对象遍历和操作, 事件处理, 动画以及 Ajax 使用的类库而已. 这是它们俩在本质上的区别. AngularJS 侧重点在于应用的架构, 而非仅仅是补充 HTML 网页的功能.

如文档所述 AngularJS 可以让你根据应用的需要对 HTML 进一步扩展. 所以, 如果想要深入的了解 AngularJS 应用开发, 就不应该再继续抱着 jQuery 的大腿. jQuery 只会把程序员的思维方式限制在现有的 HTML 标准里头.

DOM操作应该出现在指令中,但这并不意味着一定要使用jQuery包装集。在使用jQuery前要考虑到一些功能AngularJS已经提供了。指令建立于相互之间,并可以创建有用的工具。

总有一天,使用jQuery库是必要的,不过从一开始就引入它无疑是一个错误。

总结 

AngularJS是一个很不错的框架,并且和它的社区一起发展着。符合习惯的AngularJS仍旧是一个正在发展的概念,但希望以上这些对于规划一个AngularJS应用时会出现的陷阱希望可以被避免。 

AngularJS 的详细介绍请点这里
AngularJS 的下载地址请点这里

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

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