扩展AngularJS控制器的推荐方法是什么?

2022-08-30 01:25:41

我有三个非常相似的控制器。我想要一个控制器,这三个控制器扩展并共享其功能。


答案 1

也许不扩展控制器,但可以扩展控制器或使单个控制器混合使用多个控制器。

module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
    // Initialize the super class and extend it.
    angular.extend(this, $controller('CtrlImpl', {$scope: $scope}));
    … Additional extensions to create a mixin.
}]);

创建父控制器时,还会执行其中包含的逻辑。有关但只需要传递值的详细信息,请参阅 $controller()。所有其他值将正常注入。$scope

@mwarren,您的问题通过Angular依赖注入自动神奇地得到解决。您所需要的只是注入$scope,尽管如果需要,您可以覆盖其他注入的值。举个例子:

(function(angular) {

	var module = angular.module('stackoverflow.example',[]);

	module.controller('simpleController', function($scope, $document) {
		this.getOrigin = function() {
			return $document[0].location.origin;
		};
	});

	module.controller('complexController', function($scope, $controller) {
		angular.extend(this, $controller('simpleController', {$scope: $scope}));
	});

})(angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>

<div ng-app="stackoverflow.example">
    <div ng-controller="complexController as C">
        <span><b>Origin from Controller:</b> {{C.getOrigin()}}</span>
    </div>
</div>

虽然$document在由“complexController”创建时不会传递到“simpleController”中,$document被注入到我们体内。


答案 2

对于继承,您可以使用标准的 JavaScript 继承模式。这是一个演示,它使用$injector

function Parent($scope) {
  $scope.name = 'Human';
  $scope.clickParent = function() {
    $scope.name = 'Clicked from base controller';
  }    
}

function Child($scope, $injector) {
  $injector.invoke(Parent, this, {$scope: $scope});
  $scope.name = 'Human Child';
  $scope.clickChild = function(){
    $scope.clickParent();
  }       
}

Child.prototype = Object.create(Parent.prototype);

如果您使用语法(我强烈推荐),则使用经典继承模式会更容易:controllerAs

function BaseCtrl() {
  this.name = 'foobar';
}
BaseCtrl.prototype.parentMethod = function () {
  //body
};

function ChildCtrl() {
  BaseCtrl.call(this);
  this.name = 'baz';
}
ChildCtrl.prototype = Object.create(BaseCtrl.prototype);
ChildCtrl.prototype.childMethod = function () {
  this.parentMethod();
  //body
};

app.controller('BaseCtrl', BaseCtrl);
app.controller('ChildCtrl', ChildCtrl);

另一种方法是只创建“抽象”构造函数,这将是你的基本控制器:

function BaseController() {
  this.click = function () {
    //some actions here
  };
}

module.controller('ChildCtrl', ['$scope', function ($scope) {
  BaseController.call($scope);
  $scope.anotherClick = function () {
    //other actions
  };
}]);

有关此主题的博客文章