AngularJs“控制器作为”语法澄清?
我读了 angularJS有关controller as xxx
的新语法
语法
InvoiceController as invoice
告诉Angular实例化控制器并将其保存在当前范围的变量发票中。
可视化:
好吧,所以我不会有我的控制器中的参数$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
题
这样做的目标是什么? 从一个地方移除并添加到另一个地方?
我会很高兴看到我错过了什么。
有几件事情。
有些人不喜欢$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>
同样的例子,但更清晰的阅读。
-
$scope
plunker -
controller as
plunker
controller as
语法的主要优点我看到的是,你可以使用控制器作为类,而不是一些$范围装饰功能,并利用继承。 当有一个功能与一些控制器非常相似时,我经常遇到这种情况,而最明显的做法是创建一个BaseController
类并继承它。
尽管有$ scope继承,这部分解决了这个问题,但有些人更喜欢用更多的OOP方式编写代码,在我看来,代码更容易推理和测试。
这是一个演示小提琴: http : //jsfiddle.net/HB7LU/5796/
当你有嵌套的作用域时,我相信一个特别的优点是很明显的。 现在可以清楚地知道属性参考的范围是什么。
资源
使用$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; } });
上面我们用三个变量和一个行为创建AddController,使用$ scope对象控制器和视图,它们相互交谈。 $ scope对象用于将数据和行为传递给视图。 它将视图和控制器粘合在一起。
本质上,$ scope对象执行以下任务:
-
将数据从控制器传递到视图
-
将行为从控制器传递到视图
-
将控制器和视图粘合在一起
-
当$ scope对象的属性改变时,$ scope对象在视图改变时被修改,并且视图被修改
我们将属性附加到$ scope对象以将数据和行为传递给视图。 在控制器中使用$ scope对象之前,我们需要将它作为依赖关系在控制器函数中传递。
使用“controller as”语法和vm
我们可以使用controller作为语法和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; } });
本质上,我们将这个分配给一个变量虚拟机,然后附加一个属性和行为。 在视图上,我们可以使用控制器作为语法来访问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对象并附加属性和行为。 但是,通过使用控制器作为语法,控制器上的代码非常干净,只有别名在视图中可见。
以下是使用控制器作为语法的一些步骤:
-
创建一个没有$ scope对象的控制器。
-
将其分配给一个局部变量。 我首选变量名称为vm,您可以选择任意名称。
-
将数据和行为附加到vm变量。
-
在视图中,使用控制器作为语法给控制器一个别名。
-
你可以给任何名称的别名。 我宁愿使用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语法。
我将结束这篇文章,说纯粹是你的选择是否要使用控制器作为语法或$ scope对象。 没有任何巨大的优势或劣势,简单地说,控制器作为语法,你有上下文的控制是更容易处理,鉴于在视图上的嵌套控制器明确分离。
我发现主要的优点是更直观的api,因为方法/属性直接与控制器实例关联,而不是作用域对象。 基本上,用旧的方法,控制器就成了构建范围对象的一个装饰。
这里有一些关于这方面的更多信息: http : //www.syntaxsuccess.com/viewarticle/551798f20c5f3f3c0ffcc9ff
从我读过的,$ scope将被删除在Angular 2.0中,或者至少我们如何看待$ scope的使用。 随着2.0版本的发布,开始使用控制器可能会很好。
视频链接在这里进行更多的讨论。