我使用babel,gulp和browserify来构建我的应用程序。
我有简单的控制器,像这样:
export default class MyCtrl() {
constructor() {
}
someMethod() {
// I know that this is not pure code, but it is not part of current question
return $http.post('/api/some/url/', {some: 'data'});
}
}
问题在于依赖注入(DI)。这在构造函数中使用'ng-annotate'很简单:
// @ngInject
constructor($http) {
// $http is resolved here
}
但不使用其他方法:
// @ngInject
someMethod($http) {
// FAIL. $http is resolved, because angular DI working only on main ctrl function
}
我找到了解决这个问题的4种不同方法:
// 1, using this
constructor($http) {
this.http = $http;
}
someMethod() {
this.http.get(...);
}
// 2, using WeekMap
var deps = new WeekMap()
class MyCtrl {
constructor($http) {
deps.set(this, {http: $http)
}
someMethod() {
deps.get(this).http.get(...);
}
}
// 3, using inherited class
class Injectable {
constructor() {
var injector = angular.element(document).injector();
for (var prop in this) {
let fn = this[prop];
if(angular.isFunction(fn)) {
this[prop] = function(...args) {
injector.invoke(fn, this, args);
}
}
}
}
}
class MyCtrl extends Injectable {
constructor() {
super()
}
someMethod($http) {
$http.get(...)
}
// but then I can't use not injected values =(
//someAnotherMethod(valueFromCtrl, $http) {
//}
}
// 4, manually using injector
function di(...args) {
var injector = angular.element(document).injector()
if(args.length == 1) {
return injector.get(args[0])
}
var ret = args.map( name => injector.get(name) )
return args.length > 1 ? ret : ret[0];
}
class MyCtrl extends Injectable {
constructor() {
}
someMethod($http) {
var $http = di('$http');
$http.get(...)
}
}
1和2方法需要为每个依赖项提供大量代码。 3方法从控制器传递给方法的值有问题 我认为最好的方法是4号,但不确定是否还有其他问题。
问题是哪种方法更强大? 在ES clasess子方法中使用DI有什么最佳实践吗?
// UPD 方法1和2需要大量额外代码,例如对于工厂:
export default class SomeFactory {
constructor($http) {
this.$http = $http
}
getItems() {
this.$http.get('/').then(console.log.bind(console))
}
static makeFactory($http) {
return new SomeFactory($http)
}
}
angular.module('someModule', []).factory(SomeFactory.makeFactory)