AngularJS中控制器声明的差异

时间:2016-02-11 10:06:09

标签: angularjs angularjs-controller

我已经看到控制器以两种方式声明,如下所示。但是这会产生什么差异呢?

  1. appmodule.controller('Actrl',['$scope',function($scope) {}]);
  2. appmodule.controller('Actrl',function($scope) {});
  3. 但是,大多数时候,第一次不起作用。为什么呢?

3 个答案:

答案 0 :(得分:5)

两种语法都是相同的,但第一个是首选的(如果你正在缩小你的代码,那么就会有一个错字,见下面的描述)

Angular根据名称解析依赖关系,因此当您编写appmodule.controller('Actrl',function($scope) {});语法时,Angular会通过读取参数名$scope来注入$scope的依赖关系。但是当您的代码缩小以用于生产级别时,您的代码将变为:

appmodule.controller('Actrl', function(a) {});

现在,Angular将无法使用名称a来解析依赖项。这就是使用第一种方法即appmodule.controller('Actrl',['$scope', function($scope) {}]);的原因。现在,当您的代码最小化以进行生产时,您的代码将如下所示:

 appmodule.controller('Actrl',['$scope', function(a) {}]);

现在,Angular可以匹配a$scope的基于索引的位置。

您的代码中存在拼写错误,在function声明之前不应关闭该列表。

内联数组注释主题下阅读Dependency Annotation以获取更多相关信息。

  

Angular调用某些函数(如服务工厂和服务器)   控制器)通过注射器。您需要注释这些功能   注入器知道注入函数的服务。   有三种方法可以使用服务名称注释代码   信息:

     
      
  • 使用内联数组注释(首选)
  •   
  • 使用$ inject属性注释
  •   
  • 隐含地来自函数参数名称(有警告)
  •   

修改 关于两种不同风格的另一个更详细的描述:a-note-on-minification

  

因为Angular从名称中推断出控制器的依赖关系   控制器的构造函数的参数,如果你是   缩小PhoneListCtrl控制器的JavaScript代码,全部   函数参数也将被缩小,并且依赖性   注入器无法正确识别服务。

     

我们可以通过使用名称注释函数来克服这个问题   依赖关系,以字符串形式提供,不会被缩小。   有两种方法可以提供这些注射注释:

答案 1 :(得分:3)

[编辑] 对于您的第一种情况,这不是正确的语法。正确的是将依赖注入和控制器封装在同一个数组中,如下所示:

appmodule.controller('Actrl',['$scope', function($scope) {}]);

两个定义之间的区别在于,在第一种情况下,您将明确指定注入依赖项。这将避免在缩小期间重命名变量名称,这会破坏您的代码。因此引号中的名称[即这些字符串]将用于缩小版本。

两种方法都做同样的事情,但第二种方法只是第一种方法的语法糖。

答案 2 :(得分:2)

这只是AngularJS进行Dependancy Injection的两种方式。但是这个版本,

appmodule.controller('Actrl',['$scope',function($scope) {}]);

特别是为了处理代码缩小而编写的。建议尽可能使用此版本。

为了明确区别,您必须首先了解AngualarJS如何进行依赖注入。有关详细信息,请参阅:

  1. Understanding Dependency Injection
  2. The "Magic" behind AngularJS Dependency Injection
  3. AngularJS Dependency Injection - Demystified
  4. 但简而言之,AngularJS通过参数列表中的名称循环遍历每个项目,查找可以注入的已知对象名称列表,然后在匹配时注入对象。< / p>

    我们来看一个例子:

    appmodule.controller('myController',function($scope, $log) {
        $log.info($scope);
    });
    

    此处,由于$scope$log您在参数列表中指定它们的顺序无关紧要)是AngularJS的已知对象,它会将它们注入进入myController。但如果你这样做:

    appmodule.controller('myController',function(someVar) {
         // ...
    });
    

    AngularJS不知道参数someVar,它会引发依赖性错误。

    现在让我们回到你的例子。让我稍微修改你的第二版:

    appmodule.controller('Actrl',function($scope, $log) {
        $log.info($scope);
    });
    

    如果我们使用minifier,让我们看看这段代码是如何被缩小的。我为此目的使用online minifier。缩小后,它变为:

    appmodule.controller("Actrl",function(o,l){l.info(o)});
    

    这是因为,minifiers通常会将变量名缩短为最小尺寸以节省空间。注意我们$scope如何重命名为o$log改为l

    现在,如果我们运行此代码,AngularJS不会知道ol,并且我们会在前面已经理解的情况下对缺少的依赖关系感到愤怒。

    AngularJS在您的示例中使用第一版依赖注入处理此问题。如果是:

    appmodule.controller('Actrl',['$scope','$log', function($scope, $log) {
        $log.info($scope);
    }]);
    

    缩小后,它变为:

    appmodule.controller('Actrl',['$scope','$log',function(o,l){l.info(o)}]);
    

    此处,即使$scope$log参数分别重命名为ol,缩小器也不会触及字符串'$scope'和{ {1}}及其在数组中的顺序。

    现在,当AngularJS注入器使用数组看到此版本时,它会将函数中参数列表中的每个项目替换为数组中的相应对象(前提是AngularJS已知对象)。

    因此,在我们的示例中,即使在缩小之后,AngularJS也知道它需要将'$log'替换为o而将$scope替换为l。因此代码运行时没有任何Dependancy Injection错误。

    但重要的是要注意的是,当我们使用这个版本时,数组中指定的项目的顺序和函数的参数列表确实很重要。也就是说,如果你这样做:

    $log

    ,它会把一切都搞砸了!