我目前在使用角度组件注入原理时遇到问题。我有一个标题组件,必须在另一个我称为WelcomePage组件时使用。我的目标是标头组件可以使用其父组件的方法和属性。为此,我创建了以下抽象类:
export abstract class WelcomeInterface {
default: any;
languagesSorted: any;
/**
* Change app language
* @param langSelect language choice
*/
abstract onChangeLang(langSelect: string): void;
}
然后 WelcomePage 类实现 WelcomeInterface。我还向父组件添加了一个提供程序,以允许 Header 在注入后使用这些方法。
这是欢迎页面组件
@Component({
selector: 'app-welcome-page',
templateUrl: './welcomePage.component.html',
providers: [{ provide: WelcomeInterface, useClass: forwardRef(() => WelcomePageComponent) }]
})
/**
* *summary
*
* *summay
*/
export class WelcomePageComponent implements OnInit, OnDestroy, WelcomeInterface {
getPaySubscription: Subscription;
default: { value: string, flag: string };
languages = new Array<{ value: string, flag: string }>();
languagesSorted = new Array<{ value: string, flag: string }>();
isClosed: boolean;
loading: boolean;
urlJson = './assets/i18n/languages.json';
paymentMode: string;
orderId: any;
image: string;
paymentModeConstants = AppConstants.paymentModes;
routerEventSubscription: Subscription;
navEventSubscription: Subscription;
………
我遇到的问题是标题组件在其生命周期中根本看不到 WelcomePage 属性的更新。 这会导致我的应用程序中出现完全显示错误。
这就是我编写标头组件的方式
import { Component, OnInit, Input, Optional } from '@angular/core';
import { WelcomeInterface } from 'src/app/models/welcomeInterface';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
constructor(@Optional() public welcomePage: WelcomeInterface) {
}
ngOnInit() {
}
}
在我的标题组件的视图下方
<header class="header bluegreengradient">
<div *ngIf="welcomePage" class="control has-icons-left is-right">
<!-- can display if src= appConfig.settings.appLogo -->
<div class="select is-small">
<select #langSelect (change)="welcomePage.onChangeLang(langSelect.value)">
<option *ngFor="let lang of welcomePage.languagesSorted">{{lang.value}}</option>
</select>
<div class="icon is-small is-left">
<i class="flag-icon flag-icon-{{ welcomePage.default? welcomePage.default.flag:'earth'}}"></i>
</div>
</div>
</div>
<div class="container">
<h1 *ngIf="welcomePage" class="heading1">
<!-- create img source, add h1 can display if src= appConfig.settings.appLogo -->
<figure><img alt="logo" [src]="imageSrc"></figure>
</h1>
<h2 id="welcome-message" class="heading2 is-uppercase">
<!-- replace by headerTitle-->
{{ headerText | translate}}
</h2>
</div>
</header>
您的问题是您使用useClass
DI 提供程序的配方,而应该使用useExisting
.
如果出现useClass
则创建一个与角度视图树没有连接的新实例。
useExisting
键可确保子组件将获取父组件的真实现有实例。
providers: [{ provide: Interface, useExisting: forwardRef(() => AppComponent) }]
^^^^^^^^^^^
take current instance of AppComponent
堆栈闪电战示例
要解决您的问题,您需要将 useClass 更改为 use存在 像这样。
providers: [{ provide: WelcomeInterface, useExisting: forwardRef(() => WelcomePageComponent) }]
在此处查看堆栈闪电战以获取概念验证。这是因为使用 use 类时,您可以为子对象提供一个新对象而不是父对象。
这不是在角度组件之间实现双向通信的正确方法。您应该使用@Input
和@output
来实现此目的。
import { Component, OnInit, Input, Optional } from '@angular/core';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
@Input() languages: [];
@Output() valueChange = new EventEmitter();
constructor() {
}
ngOnInit() {
}
onSelectChange(value) {
this.valueChange.emit(value);
}
}
在您的父组件中
<app-header [languages]="sortedLanguages" (valueChange)="onChangeLang($event)"><app-header>
你的代码是错误的。
为了传达两个组件,您应该使用:
@Input
将数据从父级传递到子级,并且
@Output
触发从子项到父项的事件
如果您不想向组件注入某些服务,可以遵循以下语法:
@Injectable()
export class MyService { ... }
并将其注入到您的组件中,如下所示:
@Component({
...
})
export class MyComponent {
...
constructor(private myService: MyService)
}
PS:如果"我的组件"有一个模块,你也必须把你的服务放在那里,例如:
@NgModule({
...
declarations: [MyComponent],
providers: [MyService}
})
export class MyModule { }