AngularJS 开发者最常犯的 10 个错误
介绍
AngularJS是如今最受欢迎的JS框架之一,简化开发过程是它的目标之一,这使得它非常适合于元型较小的apps的开发,但也扩展到具有全部特征的客户端应用的开发。易于开发、较多的特征及较好的效果导致了较多的应用,伴随而来的是一些陷阱。本文列举了AngularJS的一些共同的易于也问题的地方,尤其是在开发一个app的时候。
1. MVC目录结构
AngularJS是一个缺乏较好的term的MVC框架,其models不像backbone.js中那样做为一个框架来定义,但其结构模式仍匹配的较好。当在一个MVC框架中作业时,基于文件类型将文件组合在一起是其共同的要求:
templates/
_login.html
_feed.html
app/
app.js
controllers/
LoginController.js
FeedController.js
directives/
FeedEntryDirective.js
services/
LoginService.js
FeedService.js
filters/
CapatalizeFilter.js
这样的布局, 尤其是对那些有 Rails 背景的人来说, 看起来挺合理. 可是当 app 变得越来越庞大的时候, 这样的布局结构会导致每次都会打开一堆文件夹. 无论你是用 Sublime, Visual Studio, 还是 Vim with Nerd Tree, 每次都要花上很多时间滑动滚动条浏览这个目录树来查找文件.
如果我们根据每个文件隶属的功能模块来对文件分组, 而不是根据它隶属的层:
app/
app.js
Feed/
_feed.html
FeedController.js
FeedEntryDirective.js
FeedService.js
Login/
_login.html
LoginController.js
LoginService.js
Shared/
CapatalizeFilter.js
那么查找某个功能模块的文件就要容易得多, 自然可以提高开发的速度. 也许把 html 文件跟 js 文件放在混合放在一起做法不是每个人都能认同. 但是起码它省下宝贵的时间.
2、模块分组
一开始就将主模块中所有子模块展示出来是通常的做法。但是开始做一个小应用还好,但是做大了就不好管理了。
var app = angular.module('app',[]);app.service('MyService', function(){
//service code});app.controller('MyCtrl', function($scope, MyService){
//controller code});
一个比较好的办法是将相似类型的子模块分组:
var services = angular.module('services',[]);services.service('MyService', function(){
//service code});var controllers = angular.module('controllers',['services']);controllers.controller('MyCtrl', function($scope, MyService){
//controller code});var app = angular.module('app',['controllers', 'services']);
这个方法与上面那个方法效果差不多,但是也不很大。运用要分组的思想将使工作更容易。
var sharedServicesModule = angular.module('sharedServices',[]);
sharedServices.service('NetworkService', function($http){});
var loginModule = angular.module('login',['sharedServices']);
loginModule.service('loginService', function(NetworkService){});
loginModule.controller('loginCtrl', function($scope, loginService){});
var app = angular.module('app', ['sharedServices', 'login']);
当创建一个大的应用时,所有模块可能不会放在一页里,但是将模块根据类型进行分组将使模块的重用能力更强。
3 依赖注入
依赖注入是AngularJS最棒的模式之一。它使测试变得更加方便,也让它所依赖的对象变的更加清楚明白。AngularJS 对于注入是非常灵活的。一个最简单的方式只需要为模块将依赖的名字传入函数中:
var app = angular.module('app',[]);app.controller('MainCtrl', function($scope, $timeout){
$timeout(function(){
console.log($scope);
}, 1000);});
这里,很清楚的是MainCtrl依赖于$scope和$timeout。
直到你准备投入生产并压缩你的代码。使用UglifyJS,上面的例子会变成:
var app=angular.module("app",[]);
app.controller("MainCtrl",function(e,t){t(function(){console.log(e)},1e3)})
现在AngularJS怎么知道MainCtrl依赖什么?AngularJS提供了一个非常简单的解决方案:把依赖作为一个字符串数组传递,而数组的最后一个元素是一个把所有依赖作为参数的函数。
app.controller('MainCtrl', ['$scope', '$timeout', function($scope, $timeout){
$timeout(function(){
console.log($scope);
}, 1000);}]);
接下来在压缩的代码中AngularJS也可以知道如何找到依赖:
app.controller("MainCtrl",["$scope","$timeout",function(e,t){t(function(){console.log(e)},1e3)}])
希望你喜欢,并分享我的工作~带你走近AngularJS系列:
- 带你走近AngularJS - 基本功能介绍 http://www.linuxidc.com/Linux/2014-05/102140.htm
- 带你走近AngularJS - 体验指令实例 http://www.linuxidc.com/Linux/2014-05/102141.htm
- 带你走近AngularJS - 创建自定义指令 http://www.linuxidc.com/Linux/2014-05/102142.htm
3.1 全局依赖
通常在写AngularJS应用时会有一个对象作为依赖绑定到全局作用域中。这意味着它在任何AngularJS的代码中都可用,但这打破了依赖注入模型同时带来一些问题,特别是在测试中。
AngularJS把这些全局变量封装到模块中,这样它们可以像标准AngularJS模块一样被注入。
Underscore.js是很棒的库,它把Javascript代码简化成了函数模式,并且它可以被转化成一个模块:
var underscore = angular.module('underscore', []);underscore.factory('_', function() {
return window._; //Underscore must already be loaded on the page});var app = angular.module('app', ['underscore']);app.controller('MainCtrl', ['$scope', '_', function($scope, _) {
init = function() {
_.keys($scope);
}
init();}]);
它允许应用继续用AngularJS依赖注入的风格,也让underscore在测试的时候被交换出来。
这或许看上去不重要,像是一个无关紧要的工作,但如果你的代码正在使用use strict(应该使用),那么这就变得有必要了。