第一种方法,使用“私有”方法并通过公共别名公开它们,称为显示模块模式,尽管在示例中这些方法实际上并不是私有的。
后者是一个非常标准的Constructor Pattern,使用 $scope 作为上下文。
variable
在 AngularJS 中使用绑定函数/第一类函数而不是私有方法命名是否有性能或风格上的原因?
[有] 推荐的方式来构建 Angular 代码吗?
TL;博士
从根本上说,上述两种风格之间没有太大区别。一用$scope
,二用this
。一个构造函数在闭包中定义,一个是内联定义的。
在某些情况下,您可能需要私有方法或值。this
使用变量/ vm
over也有风格和(可能无关紧要的)性能原因$scope
。这些不是相互排斥的。
您可能想要使用基本的、简单的、老式的构造器模式,并且很多人通过this
而不是通过$scope
.
您可以在控制器中允许自己的数据隐私,但大多数时候这应该由服务/工厂来利用。主要的例外是代表视图状态的数据。
请不要在控制器中使用 jQuery。
参考:
Todd Motto 的AngularJS 风格指南。
AngularJS 启动并运行
要彻底回答您的问题,我认为了解控制器的责任很重要。每个控制器的工作是向视图公开一组严格的状态和行为。简而言之,只分配给您不介意用户在您的视图中看到或玩的东西this
。$scope
有variable
问题的 ( vm
, $scope
) 是由 Controller 函数创建的实例的上下文 ( this
)。
$scope
是 Angular 的“特殊”上下文;它已经定义了一些行为供您使用(例如$scope.$watch)。$scopes
也遵循继承链,即 $scope 继承分配给其父 $scope 的状态和行为。
拿这两个控制器:
angular.module("Module")
.controller("Controller", ["$scope", function($scope) {
$scope.tab = 0;
$scope.incrementTab = function() {
$scope.tab++;
};
}])
.controller("OtherController", ["$scope", function($scope) {
// nothing
}]);
和一个视图
<div ng-controller="Controller">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
<div ng-controller="OtherController">
<p>{{ tab }}</p>
<button ng-click="incrementTab();">Increment</button>
</div>
</div>
这里的例子
您会注意到,即使我们没有$scope.tab
在 OtherController 中定义,它仍然从 Controller 继承它,因为 Controller 是它在 DOM 中的父级。在显示选项卡的两个地方,您应该看到“0”。这可能是您所指的“提升” ,尽管这是一个完全不同的概念。
当你点击第一个按钮时会发生什么?在这两个地方我们都暴露了“标签”,它们现在将显示“1”。当您按下第二个按钮时,两者也会更新和增加。
当然,我很可能不希望我的子选项卡与父选项卡的值相同。如果将 OtherController 更改为此:
.controller("OtherController", ["$scope", function($scope) {
$scope.tab = 42;
}]);
您会注意到这种行为已经改变 - tab 的值不再同步。
但现在令人困惑:我有两个不同的东西叫做“标签”。其他人稍后可能会使用“tab”编写一些代码并无意中破坏我的代码。
我们曾经通过在 , 上使用命名空间来解决这个问题$scope
,例如$scope.vm
并将所有内容分配给命名空间:$scope.vm.tab = 0;
<div ng-controller="OtherController">
<p>{{ vm.tab }}</p>
<button ng-click="vm.incrementTab();">Increment</button>
</div>
另一种方法是使用 controllerAs 语法的简单性和简洁性,this
并利用它。
.controller("OtherController", function() {
this.tab = 0;
});
<div ng-controller="OtherController as oc">
<p>{{ oc.tab }}</p>
</div>
对于习惯使用纯 JS 的人来说,这可能会更舒服,而且这种方式也更容易避免与其他 Angular 源代码冲突。您可以随时更改命名空间。由于您没有创建新$scope
实例,因此它的性能也有点“轻”,但我不确定有多少收益。
为了实现隐私,我建议将您的数据封装在服务或工厂中。请记住,控制器并不总是单例;View 和 Controller 之间存在 1:1 的关系,您可以多次实例化同一个控制器!然而,工厂和服务对象是单例的。他们非常擅长存储共享数据。
让所有控制器从单例中获取状态副本,并确保所有控制器都在使用服务/工厂上定义的行为修改单例状态。
function modalController(dataItemsService) {
var vm = this;
vm.selectedItems = dataItemsService.SelectedItems(); // get a copy of my data
vm.updateItem = dataItemService.UpdateItem; // update the source
}
但是等等,我怎么知道我的应用程序的另一部分何时更改了我的私人数据?我如何知道何时获得 SelectedItems 的新副本?这就是 $scope.$watch 发挥作用的地方:
function modalController(dataItemsService, $scope) {
var vm = this;
vm.updateItem = dataItemService.UpdateItem; // update the source
// periodically check the selectedItems and get a fresh copy.
$scope.$watch(dataItemsService.SelectedItems, function(items) {
vm.items = items;
});
// thanks $scope!
}
如果您的数据未共享,或者您的私有数据代表 View 层而不是 Model 层,那么将其保存在控制器中是完全可以的。
function Controller() {
var buttonClicked = false;
this.click = function() {
buttonClicked = true; // User can not lie and say they didn't.
};
}
最后,不要在您的控制器中使用 JQUERY,就像您的参考一样!
$("#existConfirmDialog").modal('hide');
这个例子可能不是纯粹的邪恶,但是避免在指令之外访问和修改 DOM,你不想通过修改它下面的 DOM 来破坏应用程序的其他部分。