重用控制器功能+扩展它

时间:2016-07-08 08:08:35

标签: angularjs

我有一个页面,其中包含几个结构非常相似的面板。他们各使用一个控制器。但由于它们的相似性,我重复使用控制器功能:

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。 ...因此,由于它们看起来不同并且表现不同,我不认为制定它们的指令是可行的方法。如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:1)

Angular中的控制器有效地用作构造函数。所以"继承的规则"在Javascript中适用于他们。一些扩展方法:

  1. 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);
    

    通过对代码进行最少的修改,此方法可能会为您提供所需的内容。

  2. 使用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>
    

    拥有模块系统使这种模式非常有用。

  3. 根据控制器的确切功能,并且如评论中所指出的,您可以在一个或多个服务中提取控制器的功能。然后控制器将成为这些服务的薄包装器。同样,这是否是一个好主意取决于控制器的确切功能。

  4. 至于指令:它们总是可行的方式:)你可以重用代码作为指令的控制器,而不是将它与ng-controller一起使用。您甚至可以使用具有不同模板的两个指令(例如customer.namecustomer.phone绑定)和相同的控制器。