AngularJs“ controller as”语法-澄清吗?


121

我从angularJS 阅读了有关以下内容的新语法controller as xxx

语法InvoiceController as invoice告诉Angular实例化控制器并将其保存在当前作用域的变量invoice中。

可视化

在此处输入图片说明

好的,所以$scope我的控制器中没有参数,并且控制器中的代码更加简洁。

我将不得不在视图中指定另一个别名

所以直到现在我都可以做:

<input type="number" ng-model="qty"  />

....controller('InvoiceController', function($scope) {
   // do something with $scope.qty <--notice

现在我可以做:

 <input type="number" ng-model="invoic.qty"  /> <-- notice 

  ....controller('InvoiceController', function() {
       // do something with  this.qty  <--notice

这样做的目的是什么?从一个地方移走并添加到另一个地方?

我将很高兴看到我在想什么。


8
该视频很好地说明了这一点。youtube.com/watch?v=tTihyXaz4Bo 我认为它用于HTML中的更干净的代码。
Fizer Khan 2014年

1
明晰。我并不担心在控制器中使用$ scope.x与this.x,但是在我看来绑定到{{invoice.x}}不仅可以告诉我{{x}}(imho)。另外,我想知道是否可以解决我在控制器中非对象存在问题的角度问题(所以things.x会很好,但x会引起问题)。
马特·罗伯茨

1
@MattRoberts处理您的最后评论-您引用的非对象问题与javascript原型继承的事实一样,并不是一个尖锐的问题。有一个很好的解释为什么它在这里成角度出现(以及为什么要controller as修复它)。
Russ Matney 2014年

我将如何替换$ scope。$ broadcast?在这种情况下,新的,因为我的这个$广播似乎并不奏效
拉夫

1
@Gaurav你仍然可以注入$范围服务到控制器中,即使您使用的控制器语法一些属性,方法,等等
德里克

Answers:


163

关于它有几件事。

有些人不喜欢$scope语法(不要问我为什么)。他们说可以使用this。这是目标之一。

弄清楚属性的来源也非常有用。

您可以嵌套控制器,并且在读取html时,很清楚每个属性的位置。

您还可以避免一些点规则问题。

例如,有两个名称都相同的控制器,您可以执行以下操作:

<body ng-controller="ParentCtrl">
    <input ng-model="name" /> {{name}}

    <div ng-controller="ChildCtrl">
        <input ng-model="name" /> {{name}} - {{$parent.name}}
    </div>
</body>

您可以同时修改父级和子级,这没有问题。但是您需要使用它$parent来查看父级的名称,因为您已在子级控制器中对其进行了阴影处理。在大量的html代码中$parent可能会出现问题,您不知道该名称的来源。

有了controller as您就可以做到:

<body ng-controller="ParentCtrl as parent">
    <input ng-model="parent.name" /> {{parent.name}}

    <div ng-controller="ChildCtrl as child">
      <input ng-model="child.name" /> {{child.name}} - {{parent.name}}
    </div>
</body>

相同的示例,但是阅读起来要清晰得多。


10
这也是一个很好的例子,说明为什么这种方法可能会使某些人困惑:stackoverflow.com/questions/25405543/…–
朱利安·霍尔曼

当您嵌套控制器时,这非常有帮助!
C_J

1
对于您的答案的类似实现,我遇到了麻烦,请参阅stackoverflow.com/questions/38315538
Cody,2016年

这还允许您使用es6类作为控制器,并引用HTML中的方法。foo() { ... }比干净得多$scope.foo = function() { ... }
Brian McCutchon '16

17

controller as我看到的语法的主要优点是,您可以将控制器作为类来使用,而不仅仅是某些$ scope装饰函数,并且可以利用继承。我经常遇到一种情况,即它的功能与许多控制器非常相似,最明显的事情是创建一个BaseController类并从中继承。

即使有$ scope继承可以部分解决此问题,但有些人还是喜欢以一种更加面向对象的方式编写代码,我认为这使代码更易于推理和测试。

这里有个小提琴来演示:http : //jsfiddle.net/HB7LU/5796/


1
这应该得到更多的支持,因为小提琴真的很有帮助
Mawg说恢复Monica


7

资源

使用$scope object和使用“controller as”语法和vm 创建控制器之间的区别

使用$ scope对象创建一个控制器

通常,我们使用$ scope对象创建一个控制器,如下清单所示:

myApp.controller("AddController", function ($scope) {



    $scope.number1;

    $scope.number2;

    $scope.result;

    $scope.add = function () {

        $scope.result = $scope.number1 + $scope.number2;

    }

});

上面,我们使用$ scope对象控制器和视图创建了具有三个变量和一个行为的AddController,它们相互通信。$ scope对象用于将数据和行为传递给视图。它将视图和控制器粘合在一起。

本质上,$ scope对象执行以下任务:

  1. 将数据从控制器传递到视图

  2. 将行为从控制器传递到视图

  3. 胶合控制器并一起查看

  4. $ scope对象在视图更改时被修改,而视图在$ scope对象的属性更改时被修改

我们将属性附加到$ scope对象,以将数据和行为传递给视图。在控制器中使用$ scope对象之前,我们需要在控制器函数中将其作为依赖项传递。

使用“ controller as”语法和vm

我们可以使用该控制器作为语法和vm变量来重写上述控制器,如下清单所示:

myApp.controller("AddVMController", function () {

    var vm = this;

    vm.number1 = undefined;

    vm.number2=undefined;

    vm.result =undefined;

    vm.add = function () {

        vm.result = vm.number1 + vm.number2;

    }

});

本质上,我们将其分配给变量vm,然后向其附加属性和行为。在视图上,我们可以使用controller作为语法访问AddVmController。这在下面的清单中显示:

<div ng-controller="AddVMController as vm">

            <input ng-model="vm.number1" type="number" />

            <input ng-model="vm.number2" type="number" />

            <button class="btn btn-default" ng-click="vm.add()">Add</button>

            <h3>{{vm.result}}</h3>

  </div>

当然,我们可以在控制器中使用除“ vm”之外的其他名称作为语法。在幕后,AngularJS创建$ scope对象,并附加属性和行为。但是,通过使用控制器作为语法,该代码在控制器上非常干净,并且在视图上仅可见别名。

以下是将控制器用作语法的一些步骤:

  1. 创建一个没有$ scope对象的控制器。

  2. 将此分配给局部变量。我将变量名首选为vm,可以选择任何名称。

  3. 将数据和行为附加到vm变量。

  4. 在视图上,使用控制器作为语法为控制器提供别名。

  5. 您可以给别名起任何名字。我更喜欢使用vm,除非我不使用嵌套控制器。

在创建控制器时,使用$ scope对象方法或控制器作为语法没有直接的优缺点。但是,纯粹是选择问题,将控制器用作语法可以使控制器的JavaScript代码更具可读性,并避免与此上下文相关的任何问题。

$ scope对象方法中的嵌套控制器

我们有两个控制器,如下面的清单所示:

myApp.controller("ParentController", function ($scope) {



    $scope.name = "DJ";

    $scope.age = 32;

});

myApp.controller("ChildController", function ($scope) {



    $scope.age = 22;

    $scope.country = "India";



});

属性“ age”位于两个控制器中,并且在视图上可以嵌套这两个控制器,如下面的清单所示:

<div ng-controller="ParentController">



            <h2>Name :{{name}} </h2>

            <h3>Age:{{age}}</h3>



             <div ng-controller="ChildController">

                    <h2>Parent Name :{{name}} </h2>

                    <h3>Parent Age:{{$parent.age}}</h3>

                    <h3>Child Age:{{age}}</h3>

                    <h3>Country:{{country}}</h3>

             </div>

        </div>

如您所见,要访问父控制器的age属性,我们使用$ parent.age。上下文分离在这里不是很清楚。但是使用控制器作为语法,我们可以以更优雅的方式使用嵌套控制器。假设我们有如下清单所示的控制器:

myApp.controller("ParentVMController", function () {

    var vm = this;

    vm.name = "DJ";

    vm.age = 32;

});

myApp.controller("ChildVMController", function () {

    var vm = this;

    vm.age = 22;

    vm.country = "India";



});

在视图上,这两个控制器可以嵌套,如下面的清单所示:

<div ng-controller="ParentVMController as parent">



            <h2>Name :{{parent.name}} </h2>

            <h3>Age:{{parent.age}}</h3>



            <div ng-controller="ChildVMController as child">

                <h2>Parent Name :{{parent.name}} </h2>

                <h3>Parent Age:{{parent.age}}</h3>

                <h3>Child Age:{{child.age}}</h3>

                <h3>Country:{{child.country}}</h3>

            </div>

 </div>

在作为语法的控制器中,我们具有更多易读的代码,并且可以使用父控制器的别名而不是$ parent语法来访问parent属性。

我将在这篇文章的结尾总结说,要使用控制器作为语法还是使用$ scope对象,这完全是您的选择。两者之间都没有巨大的优势或劣势,只是鉴于视图中嵌套控制器中的清晰分隔,简单地使您可以在上下文中控制作为控制器的语法。



3

从我所读的内容中,在Angular 2.0中将删除$ scope,或者至少我们将如何看待$ scope的使用。随着2.0版本的临近,最好开始使用控制器。

视频链接在这里有更多的讨论。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.