继承AngularJS指令以创建可重用的组件

时间:2013-09-19 06:32:43

标签: angularjs inheritance components directive

我一直在研究AngularJS已经研究了很多。我正在使用AngularJS指令构建可重用的自定义组件/小部件。我在这方面非常成功。但是,我希望在做同样的事情时坚持继承。 让我用一个例子来解释。

我创建了一个指令myButton,它创建了一个包含所有样式和按钮的按钮。功能。现在,我想扩展/继承此myButton以创建具有一些附加功能的myToggleButton和功能。我不想再次重写myButton功能。

我已经探索了各种选择。

  1. 正如https://gist.github.com/BrainCrumbz/5832057中所建议的那样,我创建了一个工厂/服务并将其注入指令中。但这不允许我充分利用遗产。我仍然需要重写大部分属性。

  2. 我尝试使用普通的面向对象的JavaScript进行继承,但在这种情况下,我不会使用AngulrJS指令。我想严格遵循Angular概念。

  3. 所以任何建议都会受到欢迎。

2 个答案:

答案 0 :(得分:4)

我还发现大多数继承示例都不太理想,但我提出了一个我认为很干净且允许完全继承的解决方案。

由于服务和指令中没有可用的原型信息,并且直接扩展Object并不好,因此您需要创建一个可以包含常量或非常简单的通用逻辑的高级基类。

var BaseService = function() {};
BaseService.prototype.toast = "french";
BaseService.prototype.halloween = "scary";

接下来让我们创建一个可以扩展的抽象服​​务(指令的逻辑相同)。

module.factory('AbstractDirective', function(
    $http, $q, $rootScope, $compile, $timeout) {
    $.extend(this, new BaseService);

    // Additional logic and methods should be appended onto 'this'
    this.doStuff = function() {
        alert("abstract function called");
    };

    this.halloween = 'fun';
    // If adding a variable to the prototype of this extended class is desired
    //     then this function would need to be extracted to its own variable
    //     where the prototype values can be set before the function
    //     is passed to the factory. 

    return this;
}

现在让我们创建一个实际的实现:

module.directive('DirectiveImpl', ['AbstractDirective', function(AbstractDirective) {
    $.extend(this, AbstractDirective);
    // A great part about this implementation pattern is that
    //   DirectiveImpl does not need to pass anything to construct AbstractDirective.
    // Meaning changes to AbstractDirective will have less impacts
    //   on implementing classes.

    this.doStuff = function () {
        // Call
        AbstractDirective.doStuff();
        // Implement some logic additional
        alert(this.toast + "Toast\nHalloween is " + this.halloween );
    }

    return this;
}]);

用于服务

module.factory

而不是

module.directive

当doStuff函数调用DirectiveImpl时,您将收到2个警报:

abstract function called

然后

French Toast
Halloween is fun

可以遵循类似的模式以允许控制器的完全继承,但还有一些可以使其工作。

答案 1 :(得分:2)

我使用此实现(基于Enzey的模型)来使我的指令按预期工作。

module.directive('DirectiveImpl', ['AbstractDirective', function(AbstractDirective) {
    return {
        controller: ['$scope','$element', function( $scope, $element ) {
            $.extend($scope, AbstractDirective);
            // A great part about this implementation pattern is that
            //   DirectiveImpl does not need to pass anything to construct 
            //   AbstractDirective.
            // Meaning changes to AbstractDirective will have less impacts
            //   on implementing classes.

            $scope.doStuff = function () {
                // Call
                AbstractDirective.doStuff();

                // Implement some logic additional
                alert($scope.toast + "Toast\nHalloween is " + $scope.halloween );
            } 
        },
        link: function( scope, element, opts ) {
            scope.doStuff();
        }
    }
}]);