簡體   English   中英

依賴注入創建多個實例

[英]dependency injection creating multiple instances

我有一個用於向應用程序顯示一些常見輸出的組件。 該組件被注入到其他服務中,以便那些服務可以觸發行為。 經過大量的故障排除后,我認為我已將問題追蹤到Angular的DI創建了組件的多個實例。 我創建了一個簡單的版本來說明問題。 這是Angular 2.4.x

AppModule:

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';

import {AppComponent} from './app.component';
import {TestComponent} from "./test.component";

@NgModule({
    declarations: [
        AppComponent,
        TestComponent
    ],
    imports: [BrowserModule, FormsModule, HttpModule],
    providers: [TestComponent],
    bootstrap: [AppComponent]
})
export class AppModule {
}

測試組件(這是我試圖用來顯示信息並將其用作服務的組件的簡化版本):

import {Component, OnInit} from '@angular/core';
@Component({
    selector: 'app-test',
    template: `<p>Message:</p>
    <p *ngIf="show">hi</p>`
})
export class TestComponent {
    private show: boolean = false;
    doTest() {
        setTimeout(() => {
            console.log('timeout callback');
            this.show = true;
        }, 5000);
    }
}

應用程序組件(使用我的測試組件的組件):

import {Component, OnInit} from '@angular/core';
import {TestComponent} from "./test.component";

@Component({
    selector: 'app-root',
    template:`
<h1>{{title}}</h1>
<app-test></app-test>
`
})
export class AppComponent implements OnInit{
    title = 'app works!';
    constructor(private test: TestComponent) { }
    ngOnInit() {
        this.test.doTest();
    }
}

我希望的行為是AppComponent將調用TestComponent的doTest函數,並且TestComponent將在5秒鍾后顯示“ hi”消息。

發生回調,並且我看到控制台消息,但未顯示“ hi”。 我認為這樣做可以為依賴注入提供單獨的實例,因此注入的App構造函數實例與App模板中的實例不同。

如果我的理解是正確的,我該如何做,以便在兩種情況下都屬於同一實例? 我是否錯過了實現此行為的更好方法?

您需要使用ViewChild裝飾器來訪問子組件,而不是將其注入到構造函數中。 憑直覺,您嘗試做的事情是有道理的,但它不會起作用。

請注意,正如Alexander Staroselsky在其評論中指出的那樣,您不應在providers數組中列出任何組件!

這是你需要寫的

import { Component, NgModule, ViewChild } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

@Component({
    selector: 'app-test',
    template: `
        <p>Message:</p>
        <p *ngIf="show">hi</p>
    `
})
export class AppTestComponent {
    doTest() {
        setTimeout(() => {
            console.log('timeout callback');
            this.show = true;
        }, 3000);
    }
    show = false;
}

@Component({
    selector: 'my-app',
    template: '<app-test></app-test>',
})
export class App {
    // this queries your view for elements of the type passed to the
    // ViewChild decorator factory.
    @ViewChild(AppTestComponent) test: AppTestComponent;

    ngAfterContentInit() {
        this.test.doTest();
    }
}

@NgModule({
    imports: [BrowserModule],
    declarations: [App, AppTestComponent],
    bootstrap: [App]
})
export class AppModule { }

這是一個有效的例子

https://plnkr.co/edit/DDx4INrgixsnJKiU1E0h?p=預覽

如果從您的角度來看僅使用子組件,則可以省去所有其他裝飾器和生命周期掛鈎。

例如:

@Component({
    selector: 'my-app',
    template: `
        <!-- give the child component a name for use in the template -->
        <app-test #test>
        </app-test>
        <button (click)="test.doTest()">Do Test</button>
    `,
})
export class App {}

這是一個有效的例子

https://plnkr.co/edit/nnXW2z7pbgdTk5Qzl1Sw?p=預覽

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM