我有一个带有模板的组件,该模板可以调用其他组件中的函数。
<div class="collapse list-unstyled">
<div *ngFor="let data of data1; let i=index">
<li>
<a class="dropdown-item menu-item" (click)= menu(i) >
{{data.item}}
</a>
</li>
</div>
此处菜单(i)是其他组件的功能。 因此,我想从该组件直接调用另一个组件中的函数。它们在组件之间没有父子关系。对我而言,最好的方法是什么?
答案 0 :(得分:1)
简短的答案是您不能这样做。每个组件都是一个独立的实体,除非一个组件包含在另一个组件中(父/子关系),否则它们之间没有直接的通信机制。
如果您需要构建一些可由多个组件调用的功能,请构建服务。然后,任何需要它的组件都可以访问该服务。
您甚至可以使用服务共享数据。例如,一个组件可以将一些标志设置到服务中,而另一组件可以稍后从服务中读取那些标志。
如果您认为合适,另一种选择是使用路由器并路由到其他组件。
这是我一段时间后做的图表,用于确定组件之间进行通信的一些关键技术。
答案 1 :(得分:0)
理想情况下,在这种情况下,您不希望像通常提供服务那样提供组件,如当前接受的答案所示。您可以/应该使用共享服务。我将建议一项共享服务,以允许组件之间进行所需的组件通信。
您首先需要的是一项通用服务,任何组件都可以通过IOular容器通过IoC容器注入。看起来可能像这样:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable()
export class CommonService {
menuChoosen$ = new Subject<number>();
constructor() { }
}
由于您似乎正在使用Angular 5,因此需要从应用模块中提供此服务。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { OneComponent } from './one/one.component';
import { AnotherComponent } from './another/another.component';
import { CommonService } from './common.service';
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent,
OneComponent,
AnotherComponent,
YetAnotherComponent ],
providers: [ CommonService ], // HERE
bootstrap: [ AppComponent ]
})
export class AppModule { }
CommonService
服务公开了menuChoosen$
Subject,任何组件都可以在需要知道何时选择菜单项时订阅。在选择了菜单项的组件中,您注入了公共服务,并在选择了菜单选项时在主题上调用next
函数。
import { Component, OnInit } from '@angular/core';
import { CommonService } from '../common.service';
@Component({
selector: 'app-one',
templateUrl: './one.component.html',
styleUrls: ['./one.component.css']
})
export class OneComponent implements OnInit {
data1 = [{item: 'Menu Item 1 (index 0)'}, {item: 'Menu Item 2 (index 1)'}, {item: 'Menu Item 3 (index 2)'}];
constructor(private commonService: CommonService) { }
ngOnInit() { }
menu(index: number) {
this.commonService.menuChoosen$.next(index); // next fired here!!
}
}
OneComponent
的模板如下所示:
<div *ngFor="let data of data1; let i=index">
<li (click)="menu(i)">{{data.item}} </li>
</div>
单击列表项(菜单项)后,索引(i)值将发送到menu
函数,该函数依次调用CommonService next
的{{1}}函数主题。
随后,所有其他订阅menuChoosen$
主题的组件都会被更新。在这种情况下,menuChoosen$
是订户,并且将知道事件。见下文。
AnotherComponent
import { Component, OnInit } from '@angular/core';
import { CommonService } from '../common.service';
@Component({
selector: 'app-another',
templateUrl: './another.component.html',
styleUrls: ['./another.component.css']
})
export class AnotherComponent implements OnInit {
chosenMenuIndex: number;
constructor(private commonService: CommonService) { }
ngOnInit() {
// the subscription starts below
this.commonService.menuChoosen$.subscribe(idx => {
this.chosenMenuIndex = idx;
this.menu(this.chosenMenuIndex); // local function call
console.log('menu index chosen: ', this.chosenMenuIndex);
});
}
menu(index: number) {
// do something
}
}
的模板如下。
AnotherComponent
一旦选择新菜单项,<p>
Menu Index: {{chosenMenuIndex}}
</p>
值将更新。您可以在订阅中执行应用程序所需的任何操作。
为什么与提供和注入另一个组件相比,共享或通用服务是更好的选择?它可以防止紧密耦合组件。任何给定的组件都不应该对其他组件有任何了解,除非父组件需要了解子组件。
如果您选择像提供服务一样提供组件,并将该组件注入另一个组件,则它们紧密耦合。一个组件完全依赖于另一组件。它可以从一个组件开始,取决于一个其他组件,但是可以迅速变成一个组件,这取决于另一个组件,然后是另一个,然后是另一个。接下来您会知道,当一项服务可以为您解决这些问题时,您将提供大量组件。
这里example stackblitz是使用共享服务进行组件通信。