我浏览过很多博客& 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();
})
;
缺点:不能直接从角度控制器继承,因此我们需要在工厂中封装基本控制器逻辑,然后通过实例化基本控制器类来创建相应的角度基本控制器。
JSBin:fipujoxube / edit?html,js,console,output
解决方案2(来自http://ng.malsup.com/#!/controller-inheritance-simplified):
// 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');
};
})
;
缺点:无法将方法附加到原型,因此基本控制器'这个'始终指的是基本控制器上下文,而不是继承的控制器。
JSBin:hvagonenowe / edit?html,js,console,output
解决方案3(使用RequireJS或AlmondJS):
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']);
});
缺点:
JSBin:yagahofefo / edit?html,js,console,output