为什么将控制器声明为自身内部或使用$ scope

时间:2015-02-11 11:12:12

标签: javascript angularjs

我最近开始学习和使用AngularJS,而且我还不清楚某些概念。

我的问题是:在我的应用程序中,我有一个控制器,它使用$http一旦初始化就从后端检索数据。根据CodeSchool on Angular的优秀教程,我想出了这个:

app.controller("agentController", function ($http) {
    var agentsCtrl = this;
    agentsCtrl.agents = [];
    $http.get("getAgents").success(function (data) {
        agentsCtrl.agents = data;
    });
...

HTML:

<div ng-controller="agentController as agentCtrl">
    <div ng-repeat="agent in agentCtrl.agents">
...

这很好用,但我不明白为什么我需要使用this将控制器声明为自身内部的变量。根据我的理解,因为通过这样做,我可以在$http服务中调用它,this关键字将返回错误的范围。这是对的吗?

我发现这也有效:

app.controller("agentController", function ($http, $scope) {
    $scope.agents = [];
    $http.get("getAgents").success(function (data) {
        $scope.agents = data;
    });

HTML:

<div ng-controller="agentController as agentCtrl">
    <div ng-repeat="agent in agents">
...

我想这是有效的,因为我明确地注入了范围并在服务中使用它。此外,HTML现在略有不同。在第一种情况下,我需要明确调用agentCtrl.agents,而范围只需调用agents。这仍然是因为变量现在在范围而不是控制器上声明?这是对的吗?

在类似案例中使用的最佳做法是什么?

谢谢!

4 个答案:

答案 0 :(得分:2)

你要问的是2种不同的方法 - &#34;控制器为&#34;或&#34; $ scope&#34;。

$范围

范围绑定的原始用法是:

<div ng-controller="MainController">  
  {{ someObj.someProp }}
</div>
app.controller('MainController', function ($scope) {  
  $scope.someObj = {
    someProp: 'Some value.'
  };
});

&#34;控制器为&#34;

使用此技术,您可以按如下方式使用绑定:

<div ng-controller="MainController as main">  
  {{ main.someProp }}
</div>  
app.controller('MainController', function () {  
  this.someProp = 'Some value.'
});

两者都有效,都很好。主要区别在于偏好。

尽管如此,大多数社区更喜欢“控制器”,为什么?

  1. 可读 - 您可以随时查看DOM元素并了解范围模型的约束
  2. 可测试 - 不必注入$ scope使测试代码更容易
  3. 更适合角度2.0的愿景,其中控制器更像是构造函数,而不是为$ scope添加内容的函数

答案 1 :(得分:1)

问题1:

您必须保存对范围var agentsCtrl = this的引用,因为您正在创建一个匿名函数以用作回调。当你这样做时,上下文变量(this)将是窗口。

app.controller("agentController", function ($http) {
    // this == your controller
    var agentsCtrl = this;

    $http.get("getAgents").success(function (data) {
        // Anonymous function 
        // this == Window Object
    });
});

问题2:

$ scope是应用程序控制器和视图之间的粘合剂。您可以将它作为全局变量引用,您可以从视图和控制器访问它。

$scope.agents = []; // From controller

{{ agents }} // From view (you don't need to specify the $scope variable)

我更喜欢为控制器提供别名,并在我的HTML中使用它,就像在

中一样
<div ng-controller="agentController as agentCtrl">
    <div ng-repeat="agent in agents">
...

但两种方式都是正确的,并且可以正常工作。

答案 2 :(得分:1)

this关键字是上下文关键字,当在控制器内的函数内使用时,可能会更改其上下文。捕获这种情况可以避免遇到这个问题。

例如:

app.controller('MainCtrl', function() {
  this.test = 'test';

  angular.forEach(testArray, function (item) {
    console.debug(this.test);
  });
});

this.test未定义,因为其范围已发生变化。

Plunkr

使用变量修复它:

app.controller('MainCtrl', function() {
  var vm = this;

  vm.test = 'test';
  var testArray = [
    1, 2, 3, 4
  ];

  angular.forEach(testArray, function (item) {
    console.debug(vm.test);
  });
});

Plunkr

取自John Papa's style guide

的原始声明

答案 3 :(得分:1)

这是为了回答你对Ben Diamant的回答的评论。

less traditional alias syntaxas Alias)简化了您的代码,可能会让您更清楚地了解您正在尝试对阅读代码的人做些什么。

来自ng-controller spec

  

使用controller as

     
      当多个控制器应用于元素时,
  • 显示您在模板中访问哪个控制器。

  •   
  • 如果您将控制器编写为类,则可以更轻松地访问属性和方法,这些属性和方法将显示在范围内,   来自控制器代码内部。

  •   
  • 因为总有一个。在绑定中,您不必担心原型继承掩盖原语。
  •   

Check out also this awesome explanation of the advantages of alias syntax

在这些优势中,最重要的是别名语法允许您

  

参考我们希望参考的控制器并停止担心   范围继承的微妙之处。

我希望它有所帮助。