为什么要将控制器声明为自身中的变量或使用$scope



我最近开始学习和使用AngularJS,但我仍然不清楚一些概念。

我的问题是:在我的应用程序中,我有一个控制器,它在初始化后立即使用$http从后端检索数据。根据CodeSchool关于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,而对于scope,只需调用agents。这仍然是因为变量现在是在作用域上声明的,而不是在控制器上声明的?这是正确的吗?

在类似情况下使用的最佳实践是什么?

谢谢!

您正在询问两种不同的方法-"Controller as"或"$scope"。

$scope

范围绑定的原始用法是:

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

"控制器为"

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

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

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

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

  1. 可读-您可以始终查看DOM元素并了解scope的模型绑定到什么
  2. 可测试性-不必注入$scope使测试代码稍微容易一些
  3. 更适合angular 2.0的愿景,在该愿景中,控制器更像是一个构造函数,而不是一个向$scope添加内容的函数

问题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">
...

但这两种方法都是正确的,而且会很好地发挥作用。

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的风格指南

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

不太传统的别名语法(as Alias)简化了代码,并可能使您对阅读代码的人所做的事情更加清晰。

来自ng控制器规格:

使用controller as

  • 当多个控制器应用于一个元素时,可以清楚地看到您正在访问模板中的哪个控制器。

  • 如果将控制器编写为类,则可以更容易地访问将出现在作用域上的属性和方法,来自控制器代码内部。

  • 因为总有一个。在绑定中,您不必担心原型继承屏蔽基元

还可以看看这篇关于别名语法优势的精彩解释。

在这些优点中,最重要的一点是别名语法允许您进行

请咨询我们希望咨询的控制器,并停止担心范围继承的微妙之处。

我希望它能有所帮助。

最新更新