下面是完成同样功能的一个service和一个factory。
当 helloWorldService 或者 helloWorldFactory中的任何一个注入到controller里面, 他们都有一个返回字符串"Hello World"的名称为 hello方法。 这个service 的构造函数只在声明时被实例化一次,并且在这个 factory 对象每次被注入时各种互相引用, 但这个 factory还是只是被实例化了一次。 所有的 providers 都是单例的。 既然都完成同样的功能,为什么会有这两种格式存在?factory比service略微更灵活一些,因为它们可以使用new关键字返回函数(原文:Factories offer slightly more flexibility than services because they can return functions which can then be new'd)。 在其他地方,从面向对象编程的工厂模式来说。 一个factory可以是一个用于创建其他对象的对象。
这里有一个使用了前面提到的那个service和两个factory的controller 的例子。需要注意的是 helloFactory 返回的是一个函数,变量name的值是在对象使用new关键字的时候设置。
在刚入门时候最好只使用services. Factory更加适用于当你在设计一个需要私有方法的类的时候使用:
在这个例子中privateFactory含有一个不能被外部访问的私有privateFunc函数。这种使用方式services也可以实现,但是使用Factory代码结构显得更加清晰。 6 不会使用 BatarangBatarang 是用于开发和调试 AngularJS 应用的一个优秀的chrome浏览器插件。 Batarang 提供了模型浏览,可以查看Angular内部哪些模型已经绑定到作用域(scopes )。可以用于需要在运行时查看指令中的隔离作用域(isolate scopes)绑定的值。 Batarang 还提供了依赖关系图。 对于引入一个未测试的代码库, 这个工具可以快速确定哪些services应该得到更多的关注。 最后, Batarang提供了性能分析。 AngularJS 虽然是高性能开箱即用, 但是随着应用自定义指令和复杂的业务逻辑的增长,有时候会感到页面不够流畅。使用 Batarang 的性能分析工具可以很方便的查看哪些functions 在digest 周期中占用了更多的时间。这个工具还可以显示出整个监控树(full watch tree),当页面有太多的监控器(watch)时,这个功能就显得有用了。 7 太多的watchers正如上文中提到的,在外部AngularJS是很不错的。因为在一个循环消化中需要进行dirty检查,一旦watcher的数目超过2,000,循环会出现很明显的问题。(2,000仅是一个参考数,在1.3版本中AngularJS对循环消化有更为严谨的控制,关于这个Aaron Graye有较为详细的叙述) 这个IIFE(快速响应函数)可输出当前本页中的watcher的数目,只需将其复制到console即可查看详情。IIFE的来源跟Jared关于StackOverflow的回答是类似的。
使用这个,可以从Batarang的效率方面来决定watcher及watch tree的数目,可以看到在哪些地方顾在或哪些地方没有改变的数据有一个watch。 当有数据没有变化时,但在Angular中又想让它成为模板,可以考虑使用bindonce.Bindonce在Angular中仅是一个可能使用模板的指令,但没有增加watch的数目。 8 审视$scopeJavascript的基于原型的继承和基于类的继承在一些细微的方面是不同的。通常这不是问题,但是差别往往会在使用$scope时出现。在AngularJS中每一个$scope都从它的父$scope继承过来,最高层是$rootScope。($scope在指令中表现的有些不同,指令中的隔离作用域仅继承那些显式声明的属性。) 从父级那里分享数据对于原型继承来说并不重要。不过如果不小心的话,会遮蔽父级$scope的属性。 我们想在导航栏上呈现一个用户名,然后进入登陆表单。
考你下:当用户在设置了ngModel的文本框中输入了值,哪个模板会被更新?是navCtrl,loginCtrl还是两者? 如果你选loginCtrl,那么你可能对原型继承的机理比较了解了。当寻找字面值时,原型链并没有被涉及。如果navCtrl要被更新的话,那么查找原型链是必要的。当一个值时对象的时候就会发生这些。(记住在Javascript中,函数、数组合对象都算作对象) 所以想要获得期望的效果就需要在navCtrl上创建一个对象可以被loginCtrl引用。
现在既然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应用时会出现的陷阱希望可以被避免。 |