AngularJS控制器可以从同一模块中的另一个控制器继承吗?

Fed*_*les 197 inheritance angularjs angularjs-controller

在模块中,控制器可以从外部控制器继承属性:

var app = angular.module('angularjs-starter', []);

var ParentCtrl = function ($scope, $location) {
};

app.controller('ChildCtrl', function($scope, $injector) {
  $injector.invoke(ParentCtrl, this, {$scope: $scope});
});
Run Code Online (Sandbox Code Playgroud)

示例:死链接:http://blog.omkarpatil.com/2013/02/controller-inheritance-in-angularjs.html

模块内的控制器也可以继承兄弟姐妹吗?

var app = angular.module('angularjs-starter', []);

app.controller('ParentCtrl ', function($scope) {
  //I'm the sibling, but want to act as parent
});

app.controller('ChildCtrl', function($scope, $injector) {
  $injector.invoke(ParentCtrl, this, {$scope: $scope}); //This does not work
});
Run Code Online (Sandbox Code Playgroud)

第二个代码不起作用,因为$injector.invoke需要一个函数作为第一个参数,并且找不到引用ParentCtrl.

Sal*_*bas 287

是的,它可以但您必须使用该$controller服务来实例化控制器: -

var app = angular.module('angularjs-starter', []);

app.controller('ParentCtrl', function($scope) {
  // I'm the sibling, but want to act as parent
});

app.controller('ChildCtrl', function($scope, $controller) {
  $controller('ParentCtrl', {$scope: $scope}); //This works
});
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常好的解决方案.谢谢.但是,如果我使用Controller As语法,我该怎么做呢? (10认同)
  • 这对我有用,但是我试图通过在同一页面上拥有父控制器和子控制器的方式来实现这一点.这会导致父控制器中的$ http操作运行两次.当子控制器注入父控制器的范围时,我的$ scope.AllMembers数组将在父控制器使其运行时填充两次,然后子控制器使其再次运行.有什么方法可以阻止这种情况吗? (4认同)

IPr*_*ory 19

如果您使用vm控制器语法,这是我的解决方案:

.controller("BaseGenericCtrl", function ($scope) {

    var vm = this;
    vm.reload = reload;
    vm.items = [];

    function reload() {
        // this function will come from child controller scope - RESTDataService.getItemsA
        this.getItems();
    }
})

.controller("ChildCtrl", function ($scope, $controller, RESTDataService) {
    var vm = this;
    vm.getItems = RESTDataService.getItemsA;
    angular.extend(vm, $controller('BaseGenericCtrl', {$scope: $scope}));
})
Run Code Online (Sandbox Code Playgroud)

不幸的是,您不能使用$controller.call(vm, 'BaseGenericCtrl'...),将当前上下文传递给closure(for reload())函数,因此只有一个解决方案是使用this内部继承函数来动态更改上下文.


Lau*_*Skr 8

我认为,您应该使用工厂或服务,为两个控制器提供可访问的功能或数据.

这里是类似的问题---> AngularJS控制器继承


gm2*_*008 7

为了回应gmontague这个答案中提出的问题,我找到了一种使用$ controller()继承控制器的方法,并且仍然使用控制器"as"语法.

首先,在继承调用$ controller()时使用"as"语法:

    app.controller('ParentCtrl', function(etc...) {
        this.foo = 'bar';
    });
    app.controller('ChildCtrl', function($scope, $controller, etc...) {
        var ctrl = $controller('ParentCtrl as parent', {etc: etc, ...});
        angular.extend(this, ctrl);

    });
Run Code Online (Sandbox Code Playgroud)

然后,在HTML模板中,如果属性由parent定义,则用于parent.检索从parent继承的属性; 如果由child定义,则使用child.它来检索它.

    <div ng-controller="ChildCtrl as child">{{ parent.foo }}</div>
Run Code Online (Sandbox Code Playgroud)


Fab*_*olo 5

好吧,我以另一种方式做到了这一点.在我的情况下,我想要一个在其他控制器中应用相同功能和属性的功能.我喜欢它,除了参数.这样,你所有的ChildCtrls都需要获得$ location.

var app = angular.module('angularjs-starter', []);

function BaseCtrl ($scope, $location) {
    $scope.myProp = 'Foo';
    $scope.myMethod = function bar(){ /* do magic */ };
}

app.controller('ChildCtrl', function($scope, $location) {
    BaseCtrl.call(this, $scope, $location);

    // it works
    $scope.myMethod();
});
Run Code Online (Sandbox Code Playgroud)


Ada*_*eis 5

对于那些想知道的人,您可以使用已接受答案中的方法以相同的方式扩展组件控制器。

使用以下方法:

父组件(扩展自):

/**
 * Module definition and dependencies
 */
angular.module('App.Parent', [])

/**
 * Component
 */
.component('parent', {
  templateUrl: 'parent.html',
  controller: 'ParentCtrl',
})

/**
 * Controller
 */
.controller('ParentCtrl', function($parentDep) {

  //Get controller
  const $ctrl = this;

  /**
   * On init
   */
  this.$onInit = function() {

    //Do stuff
    this.something = true;
  };
});
Run Code Online (Sandbox Code Playgroud)

子组件(扩展的那个):

/**
 * Module definition and dependencies
 */
angular.module('App.Child', [])

/**
 * Component
 */
.component('child', {
  templateUrl: 'child.html',
  controller: 'ChildCtrl',
})

/**
 * Controller
 */
.controller('ChildCtrl', function($controller) {

  //Get controllers
  const $ctrl = this;
  const $base = $controller('ParentCtrl', {});
  //NOTE: no need to pass $parentDep in here, it is resolved automatically
  //if it's a global service/dependency

  //Extend
  angular.extend($ctrl, $base);

  /**
   * On init
   */
  this.$onInit = function() {

    //Call parent init
    $base.$onInit.call(this);

    //Do other stuff
    this.somethingElse = true;
  };
});
Run Code Online (Sandbox Code Playgroud)

诀窍是使用命名控制器,而不是在组件定义中定义它们。