![](/img/trans.png)
[英]Angular2 dependency injection, service not being injected during class inheritance
[英]Angular 2 own Class Decorator to access Dependency Injection Service
我想創建一個類裝飾器TopicClass
,它向裝飾組件添加一個屬性和一個函數。 該函數必須訪問注入的服務。 我怎么做?
以下是嘗試失敗的內容:
@Component({
selector: 'home',
styleUrls: ['./home.component.css'],
templateUrl: './home.component.html'
})
@TopicClass('home')
export class HomeComponent {
constructor(private topicService: TopicService) { }
}
我無法通過插入的函數ngAfterViewInit
訪問注入的 Service。
export function TopicClass(title: string) {
return function (target: Function) {
const original = target;
function construct(constructor, args) {
const c: any = function () {
return constructor.apply(this, args);
}
c.prototype = constructor.prototype;
const newInstance = new c();
newInstance['topic'] = new Topic(title, '');
newInstance['ngAfterViewInit'] = () => {
newInstance['topicService'].setTopic(newInstance['topic']);
}
return newInstance;
}
const ctor: any = (...args) => {
console.log("Service: " + original.prototype.topicService);
return construct(original, args);
};
ctor.prototype = original.prototype;
return ctor;
}
}
問題是newInstance['topicService']
未定義。
我已經建立了一個簡單的 Angular 項目進行測試: https : //github.com/ptea/angular-class-decorator-test
https://github.com/ptea/angular-class-decorator-test/blob/master/src/app/services/topic.service.ts
我還嘗試用一個簡單的 TypeScript 程序重現這個問題,它按預期工作:
newInstance['printStreet'] = () => {
console.log(`printFirstnameStreet: ${newInstance['firstname']}, ${newInstance['street']}`);
}
https://github.com/ptea/angular-class-decorator-test/blob/master/dashboard.ts
這個問題的任何想法/解決方案?
TopicService
未定義的原因是因為它從未被注入到組件中。 根據您當前的裝飾被重新定義的構造HomeComponent
是沒有參數的構造函數。 這弄亂了 Angular 的 DI,因此在實例化組件時不會注入TopicService
。
我能想到的來完成你想要什么,最好的辦法是不能修改的構造HomeComponent
,轉而進軍ngOnInit
方法來代替。 ngOnInit 方法是一個理想的候選方法,因為它在每個組件的生命周期中被調用一次,並且它有固定數量的參數,0,這使得它很容易包裝在另一個函數中。 您可以與ngAfterViewInit
函數類似地執行此操作,以便在需要時使用該服務。
以下是如何修改TopicClassDecorator
以實現您想要的結果:
export function TopicClass(title: string) {
return function (target: Function) {
let targetNgOnInit = target.prototype.ngOnInit;
target.prototype.ngOnInit = function (){
this.topic = new Topic(title, 'subTitle');
if(targetNgOnInit){
targetNgOnInit.apply(target);
}
}
let targetNgAfterViewInit = target.prototype.ngAfterViewInit;
target.prototype.ngAfterViewInit = function (){
this.topicService.setTopic(this.topic);
if(targetNgAfterViewInit){
targetNgAfterViewInit.apply(target);
}
}
return target;
}
}
一切協同工作的演示 Plunkr 。
我終於在不覆蓋 ngOnInit 函數的情況下采用了以下解決方案:
export function TopicClass(title: string) {
return function (target: Function) {
target.prototype.topic = new Topic(title);
let targetNgAfterViewInit = target.prototype.ngAfterViewInit;
target.prototype.ngAfterViewInit = function () {
this.topicService.setTopic(this.topic);
if(targetNgAfterViewInit){
targetNgAfterViewInit.apply(target);
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.