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系列:

  1. 带你走近AngularJS - 基本功能介绍
  2. 带你走近AngularJS - 体验指令实例
  3. 带你走近AngularJS - 创建自定义指令

如何在 AngularJS 中对控制器进行单元测试

在 AngularJS 应用中通过 JSON 文件来设置状态

AngularJS 之 Factory vs Service vs Provider

AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交数据

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(应该使用),那么这就变得有必要了。 

更多详情见请继续阅读下一页的精彩内容:

  • 1
  • 2
  • 3
  • 下一页

相关内容