我有一个页面,其中包含几个结构非常相似的面板。他们各使用一个控制器。但由于它们的相似性,我重复使用控制器功能:
function panelController($scope) {
...
}
angular.module('myApp.controllers')
.controller('panel1Controller', panelController);
angular.module('myApp.controllers')
.controller('panel2Controller', panelController);
结果是panel1和panel2有自己不同的范围,但就视图可以绑定的内容而言看起来是一样的。
然而,现在我正处于我想对panel3使用相同模式但略有扩展的地步。也就是说,我想要仅包含在panel3的$ scope中。理想情况下,我希望能够做到这样的事情:
function panel3ControllerExtension($scope) {
$scope.panel3Field = "I must only live in panel3";
}
angular.module('myApp.controllers')
.controller('panel3Controller', panelController, panel3ControllerExtension);
但那是不可能的。这有什么好的模式吗?
编辑: 类似的面板仅在他们期望的$ scope包含的内容中类似。具体而言,期望范围包含客户对象。所以例如panel1将$ scope.customer.name和panel2绑定到$ scope.customer.phone。 ...因此,由于它们看起来不同并且表现不同,我不认为制定它们的指令是可行的方法。如果我错了,请纠正我。
答案 0 :(得分:1)
Angular中的控制器有效地用作构造函数。所以"继承的规则"在Javascript中适用于他们。一些扩展方法:
apply
/ call
" base"功能:
function panel3Controller($scope) {
// add the functionality of `panelController` to this scope
// in OO terms this can be thought of as calling the `super` constructor
panelController.call(this, $scope);
// add panel3 specific functionality
$scope.panel3SpecificThing = "...";
}
// just register the new controller
angular.module('myApp.controllers')
.controller('panel3Controller', panel3Controller);
通过对代码进行最少的修改,此方法可能会为您提供所需的内容。
使用JS继承:使控制器成为JS"类"让子控制器原型继承它。您可能还希望将此与controller as
语法结合使用:
function PanelController($scope) {
this.$scope = $scope;
this.something = '...';
}
PanelController.prototype.someMethod = function() {
...
}
function Panel3Controller($scope) {
PanelController.call(this, $scope);
this.somethingElse = '...';
}
Panel3Controller.prototype = new PanelController();
Panel3Controller.prototype.constructor = Panel3Controller;
Panel3Controller.prototype.panel3SpecificMehod = function() {
...
};
如果您使用的是ES2015,可以简化上述内容:
class PanelController {
constructor($scope) {
...
}
...
}
class Panel3Controller extends PanelController {
constructor($scope) {
super($scope);
...
}
...
}
同样,您只需注册新控制器:
angular.module('myApp.controllers')
.controller('panel3Controller', Panel3Controller);
如果属性和方法放在控制器中,如此处所示,请使用controller as
语法,即在HTML中:
<div ng-controller="panel3Controller as p3ctrl">
<span>{{ p3ctrl.somethingElse }}</span>
拥有模块系统使这种模式非常有用。
根据控制器的确切功能,并且如评论中所指出的,您可以在一个或多个服务中提取控制器的功能。然后控制器将成为这些服务的薄包装器。同样,这是否是一个好主意取决于控制器的确切功能。
至于指令:它们总是可行的方式:)你可以重用代码作为指令的控制器,而不是将它与ng-controller
一起使用。您甚至可以使用具有不同模板的两个指令(例如customer.name
和customer.phone
绑定)和相同的控制器。