在AngularJS主页的“创建组件”部分,有这样一个例子:

controller: function($scope, $element) {
  var panes = $scope.panes = [];
  $scope.select = function(pane) {
    angular.forEach(panes, function(pane) {
      pane.selected = false;
    });
    pane.selected = true;
  }
  this.addPane = function(pane) {
    if (panes.length == 0) $scope.select(pane);
    panes.push(pane);
  }
}

注意select方法是如何添加到$scope的,而addPane方法是添加到this的。如果我把它改成$scope。addPane,代码崩溃。

文档说实际上是有区别的,但它没有提到区别是什么:

以前的Angular版本(1.0 RC之前)允许你将此方法与$scope方法互换使用,但现在不再是这样了。在作用域上定义的方法内部this和$scope是可以互换的(angular将this设置为$scope),但在控制器构造函数内部则不能互换。

this和$scope在AngularJS控制器中是如何工作的?


当前回答

以前的Angular版本(1.0 RC之前)允许你使用这个 可以与$scope方法互换,但这不再是 的情况。在作用域this和$scope上定义的方法内部 可互换(angular将其设置为$scope),否则就不行 在你的控制器构造函数中。

要恢复这种行为(有人知道为什么改变吗?)你可以添加:

return angular.extend($scope, this);

在控制器函数的末尾(假设$scope被注入到这个控制器函数中)。

这有一个很好的效果,可以通过控制器对象访问父作用域,你可以在child中使用require: '^myParentDirective'

其他回答

在本课程(https://www.codeschool.com/courses/shaping-up-with-angular-js)中,他们解释了如何使用“this”和许多其他东西。

如果你通过"this"方法向控制器添加方法,你必须在视图中用控制器名"dot"你的属性或方法来调用它。

例如,在视图中使用控制器,你可能会有这样的代码:

    <div data-ng-controller="YourController as aliasOfYourController">

       Your first pane is {{aliasOfYourController.panes[0]}}

    </div>

我建议你阅读下面的帖子: "Controller as"还是"$scope"?

它很好地描述了使用“Controller as”公开变量而不是“$scope”的优点。

我知道你特别问了关于方法而不是变量的问题,但我认为最好坚持一种技术并与之保持一致。

所以在我看来,由于文章中讨论的变量问题,最好只使用“Controller as”技术,并将其应用于方法。

我刚刚读了一篇关于两者区别的非常有趣的解释,而且越来越多的人倾向于将模型附加到控制器上,并通过别名将控制器绑定到视图上。http://toddmotto.com/digging-into-angulars-controller-as-syntax/是文章。

注意:原始链接仍然存在,但格式的变化使其难以阅读。在原版中更容易看到。

他没有提到,但是在定义指令时,如果你需要在多个指令之间共享一些东西,并且不想要一个服务(在某些情况下,服务是一个麻烦),那么将数据附加到父指令的控制器上。

$scope服务提供了很多有用的东西,$watch是最明显的,但如果您需要将数据绑定到视图,那么在模板中使用普通控制器和“controller as”是很好的,而且可以说是更可取的。

$scope有一个不同的this和控制器this。因此,如果你把console.log(this)放在控制器内部,它会给你一个对象(控制器),this.addPane()将addPane方法添加到控制器对象。但是$scope有不同的作用域,它作用域中的所有方法都需要通过$scope. methodname()访问。 this.methodName()在控制器内部意味着在控制器对象中添加方法

$scope.functionName(){
    this.name="Name";
    //or
    $scope.myname="myname"//are same}

将这段代码粘贴到编辑器中,打开控制台查看…

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>this $sope vs controller</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.7/angular.min.js"></script>
    <script>
        var app=angular.module("myApp",[]);
app.controller("ctrlExample",function($scope){
          console.log("ctrl 'this'",this);
          //this(object) of controller different then $scope
          $scope.firstName="Andy";
          $scope.lastName="Bot";
          this.nickName="ABot";
          this.controllerMethod=function(){

            console.log("controllerMethod ",this);
          }
          $scope.show=function(){
              console.log("$scope 'this",this);
              //this of $scope
              $scope.message="Welcome User";
          }

        });
</script>
</head>
<body ng-app="myApp" >
<div ng-controller="ctrlExample">
       Comming From $SCOPE :{{firstName}}
       <br><br>
       Comming from $SCOPE:{{lastName}}
       <br><br>
       Should Come From Controller:{{nickName}}
       <p>
            Blank nickName is because nickName is attached to 
           'this' of controller.
       </p>

       <br><br>
       <button ng-click="controllerMethod()">Controller Method</button>

       <br><br>
       <button ng-click="show()">Show</button>
       <p>{{message}}</p>

   </div>

</body>
</html>

以前的Angular版本(1.0 RC之前)允许你使用这个 可以与$scope方法互换,但这不再是 的情况。在作用域this和$scope上定义的方法内部 可互换(angular将其设置为$scope),否则就不行 在你的控制器构造函数中。

要恢复这种行为(有人知道为什么改变吗?)你可以添加:

return angular.extend($scope, this);

在控制器函数的末尾(假设$scope被注入到这个控制器函数中)。

这有一个很好的效果,可以通过控制器对象访问父作用域,你可以在child中使用require: '^myParentDirective'