Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript AngularJS:实现控制器原型继承的最干净方法_Javascript_Angularjs_Inheritance_Controller - Fatal编程技术网

Javascript AngularJS:实现控制器原型继承的最干净方法

Javascript AngularJS:实现控制器原型继承的最干净方法,javascript,angularjs,inheritance,controller,Javascript,Angularjs,Inheritance,Controller,我浏览了很多博客&stackoverflow线程,以找到实现兄弟控制器原型继承的最佳方法,这让我研究了3种解决方案。没有一个是完美的,每一个都有它的缺点,所以我想知道它们是否可以改进,或者是否有人有更好的解决方案 解决方案1: // helper function to achieve prototypal inheritance angular.inherit = function (childCtor, parentCtor) { childCtor.super = function

我浏览了很多博客&stackoverflow线程,以找到实现兄弟控制器原型继承的最佳方法,这让我研究了3种解决方案。没有一个是完美的,每一个都有它的缺点,所以我想知道它们是否可以改进,或者是否有人有更好的解决方案

解决方案1:

// helper function to achieve prototypal inheritance
angular.inherit = function (childCtor, parentCtor) {
    childCtor.super = function() {
        var args = Array.prototype.slice.call(arguments);
        parentCtor.apply(args.shift(), args);
    };
    childCtor.prototype = Object.create(parentCtor.prototype, {
        constructor: {
            value: childCtor,
            enumerable: false
        }
    });
    return this;
};


angular.module('test', [])

    // simple service
    .factory('animalService', function() {
        return {
            getScream: function(specy) {
                switch (specy.toLowerCase()) {
                    case 'cat':
                        return 'Meeeeoooow';
                    case 'dog':
                        return 'Waaaaaaarf';
                }
                return '???';
            }
        };
    })

    // AnimalController logic encapsulated in a factory
    .factory('AAnimalController', function ($window, animalService) {

        function AAnimalController($scope, specy) {
            this._name = 'name me!';
            this._specy = specy || 'Animal';

            $scope.$on('cat:mew', react.bind(this));
        }

        function react() {
            if (this.specy === 'Dog') {
                console.log('A cat is around?!? Attack!!!');
            }
        }

        AAnimalController.prototype = {
            introduceItself: function() {
                return 'Hello, my name is "' + this.name + '" and I\'m a ' + this.specy.toLowerCase();
            },

            scream: function() {
                $window.alert(animalService.getScream(this.specy));
            },

            get name() {
                return this._name;
            },
            set name(value) {
                this._name = value;
            },

            get specy() {
                return this._specy;
            }
        };

        return AAnimalController;
    })


    .controller('AnimalController', function ($scope, AAnimalController) {
        return new AAnimalController($scope);
    })


    .controller('DogController', function ($scope, $window, AAnimalController, $controller) {

        function DogController() {
            DogController.super(this, $scope, 'Dog');

            this.fetchStick = function() {
                $window.alert('Here\'s your stick, master!');
            };
        }

        angular.inherit(DogController, AAnimalController);

        return new DogController();
    })


    .controller('CatController', function ($rootScope, $scope, $window, AAnimalController) {

        function CatController() {
            CatController.super(this, $scope, 'Cat');

            this.purr = function() {
                $window.alert('Rrrrrrrr!');
            };

            this.scream = function() {
                AAnimalController.prototype.scream.call(this);
                $rootScope.$broadcast('cat:mew');
            };
        }

        angular.inherit(CatController, AAnimalController);

        return new CatController();
    })
;
缺点:不能直接从angular controller继承,因此我们需要在工厂中封装基本控制器逻辑,然后通过实例化基本控制器类来创建相应的angular基本控制器

JSBin:fipujoxube/edit?html、js、控制台、输出

解决方案2(来自):

缺点:无法将方法附加到原型,因此基本控制器“this”始终引用基本控制器上下文,而不是继承的控制器

JSBin:hvagonenowe/edit?html、js、控制台、输出

解决方案3(带RequireJS或AlmondJS):

缺点:

  • 冗长的
  • 附加第三方库
  • 在棱角分明的“世界”之外,我们 需要调用工厂模块才能访问其公共方法

JSBin:yagahofefo/edit?html、js、console、output

或者您可以选择组合而不是继承是的,但是如果您处于性能确实重要的情况下(多个控制器共享一个共同的行为),继承将是最合适的,因为组合会导致共享方法的创建次数与控制器数量一样多。如果您查看逻辑,您可以很容易地得到一个数据对象,即animal,它具有控制器方法随后使用的属性。所以你可以给动物设定一个反应,一声尖叫,等等。这些甚至可以设置在你的控制器之外,这样你的控制器就不需要知道这是怎么发生的。然后你的getcream()将是return animal.cream,你的react()将是console.log(animal.reaction),等等。我会尽量记住这个周末给你做一次扑救。
// helper function to achieve controller inheritance
var ngModule = angular.module;
angular.module = function() {
    var mod = ngModule.apply(this, arguments);

    mod.inheritController = function(name, inheritFrom, Ctor) {
        this.controller(name, function ($scope, $controller, $injector) {
            var locals = { $scope: $scope, this: this };
            console.log($controller(inheritFrom, locals));
            Ctor.prototype = $controller(inheritFrom, locals);
            locals.superCtrl = Ctor.prototype;
            return $injector.instantiate(Ctor, locals);
        });
        return this;
    };

    return mod;
};


angular.module('test', [])

    // service example
    .factory('animalService', function() {
        return {
            getScream: function(specy) {
                switch (specy.toLowerCase()) {
                    case 'cat':
                        return 'Meeeeoooow';
                    case 'dog':
                        return 'Waaaaaaarf';
                }
                return '???';
            }
        };
    })

    .controller('AnimalController', function ($scope, $window, animalService) {

        // 'PRIVATE' PROPERTIES
        this._name = 'name me!';
        this._specy = 'Animal';

        // PUBLIC METHODS
        /*this.listenForCat = function() {
            $scope.$on('cat:mew', react.bind(this));
        };*/

        this.introduceItself = function() {
            return 'Hello, my name is "' + this._name + '" and I\'m a ' + this._specy.toLowerCase();
        };

        this.scream = function() {
            $window.alert(animalService.getScream(this._specy));
        };

        Object.defineProperties(this, {
            name: {
                get: function() {
                    return this._name;
                },
                set: function(value) {
                    this._name = value;
                }
            },

            specy: {
                get: function() {
                    return this._specy;
                }
            }
        });

        // PRIVATE METHODS
        function react() {
            if (this.specy === 'Dog') {
                console.log('A cat is around? Attack!!');
            }
        }

        $scope.$on('cat:mew', react.bind(this));
    })

    .inheritController('DogController', 'AnimalController', function ($window, superCtrl) {
        this._specy = 'Dog';
        this.fetchStick = function() {
            $window.alert('Here\'s your stick, master!');
        };

        this.listenForCat();
    })

    .inheritController('CatController', 'AnimalController', function ($rootScope, $window, superCtrl) {
        this._specy = 'Cat';

        this.purr = function() {
            $window.alert('Rrrrrrrr!');
        };

        this.scream = function() {
            superCtrl.scream.call(this);
            $rootScope.$broadcast('cat:mew');
        };
    })
;
define('inherit', function() {
    function inherit(childCtor, parentCtor) {
        childCtor.super = function() {
            var args = Array.prototype.slice.call(arguments);
            parentCtor.apply(args.shift(), args);
        };
        childCtor.prototype = Object.create(parentCtor.prototype, {
            constructor: {
                value: childCtor,
                enumerable: false
            }
        });
        return this;
    }

    return inherit;
});

define('animalService', function() {

    function animalService() {

        return {
            getScream: function(specy) {
                switch (specy.toLowerCase()) {
                    case 'cat':
                        return 'Meeeeoooow';
                    case 'dog':
                        return 'Waaaaaaarf';
                }
                return '???';
            }
        };
    }

    return animalService;
});


define('AnimalController', ['animalService'], function (animalService) {

    animalService = animalService();

    function AnimalController($scope) {
        this._name = 'name me!';
        this._specy = 'Animal';

        $scope.$on('cat:mew', react.bind(this));
    }

    AnimalController.prototype = {
        introduceItself: function() {
            return 'Hello, my name is "' + this.name + '" and I\'m a ' + this.specy.toLowerCase();
        },

        scream: function() {
            window.alert(animalService.getScream(this.specy));
        },

        get name() {
            return this._name;
        },
        set name(value) {
            this._name = value;
        },

        get specy() {
            return this._specy;
        }
    };

    function react() {
        if (this.specy === 'Dog') {
            console.log('A cat is around?!? Attack!!!');
        }
    }

    return AnimalController;
});

define('DogController', ['AnimalController', 'inherit'], function (AnimalController, inherit) {

    function DogController($scope, $window) {
        DogController.super(this, $scope);
        this._specy = 'Dog';

        this.fetchStick = function() {
            $window.alert('Here\'s your stick, master!');
        };
    }

    inherit(DogController, AnimalController);

    return DogController;
});

define('CatController', ['AnimalController', 'inherit'], function (AnimalController, inherit) {

    function CatController($rootScope, $scope, $window, animalService) {
        CatController.super(this, $scope);
        this._specy = 'Cat';

        this.purr = function() {
            $window.alert('Rrrrrrrr!');
        };

        this.scream = function() {
            AnimalController.prototype.scream.call(this);
            $rootScope.$broadcast('cat:mew');
        };
    }

    inherit(CatController, AnimalController);

    return CatController;
});

require([
    'animalService',
    'AnimalController',
    'DogController',
    'CatController'
], function (animalService, AnimalController, DogController, CatController) {

    angular.module('test', [])
        .factory('animalService', animalService)
        .controller('AnimalController', AnimalController)
        .controller('DogController', DogController)
        .controller('CatController', CatController)
    ;

    angular.bootstrap(document, ['test']);
});