![](/img/trans.png)
[英]Angular 7 call ngOnInit method or any other method of component that is contained by component
[英]How can I call a specific public method of any component in Angular, like how `ngOnInit` works
在我的項目中,我有很多組件。 我有一個事件處理程序。 當特定事件發生時,我想通過名稱調用組件內的特定方法(如果它存在於任何組件中)。 請找到以下示例:
@Component({
...
})
export class MyComponent {
public onMyEvent() {
// do stuff on that event
}
}
在這里,我希望在事件發生時調用onMyEvent()
,如下所示:
export class MyEventHandler {
private myEvent: Subject;
public registerEvents() {
this.myEvent.subcribe(() => {
// call "onMyEvent" function of all components that exists in the view
});
}
}
該場景類似於ngOnInit()
、 ngAfterViewInit()
.. 的工作方式。 當您實現OnInit
和AfterViewInit
接口時,您正在定義一個合同,保證該組件具有指定的方法,該方法隨時可以調用。 我想做同樣的事情。
這可以使用ComponentRef
來實現。 但是只有父組件可以調用它的子組件,並且非常依賴於 HTML 結構。 我希望它像ngOnInit
一樣無縫。
我覺得這里有一些並行的概念,所以如果我的回答有誤,請原諒我。 請讓我知道哪些元素不正確,我可以相應地修改我的答案
據我了解,您需要以下內容:
onMyEvent
方法的組件 tl:dr 以實現類似ngOnInit
的體驗(無需組件配置即可開箱即用)所有組件將默認強制設置訂閱,這在架構上不是很好。 注入由組件本身確定的訂閱的 singleton 服務似乎是一種更明智的方法,但這需要您沒有生命周期掛鈎的設置,因此可能不符合“無縫”的條件
第 1 點很簡單,正如您已經提到的,我們可以為許多要實現的組件定義一個共享接口,這要求存在onMyEvent
。
export interface IEventHandler {
onMyEvent: () => void
}
export class MyComponent1 implements IEventHandler {
constructor() {}
public onMyEvent() {
// do stuff on that event
}
}
export class MyComponent2 {
constructor() {}
}
export class MyComponent3 implements IEventHandler { // error: `onMyEvent` is missing
constructor() {}
}
第 2 點需要單個 stream(即Observable
、 Subject
、 EventEmitter
等),它能夠被多個組件監視
顯而易見的解決方案是一個包含這個 stream 的服務,並且可以依賴注入到任何需要它的組件中。
export class EventHandlerService {
public myEventSubject: Subject;
}
但是,我假設您不想為每個需要它的組件生成一個唯一的服務實例,而是想要一個 singleton 服務,它向所有組件廣播相同的事件。 結果,您將訂閱事件的責任放在組件本身上,即
export class MyComponent1 implements IEventHandler {
constructor(private eventHandlerService: EventHandlerService) {}
ngOnInit() {
this.eventHandlerService.myEventSubject.subscribe({
next: () => this.onMyEvent() // guaranteed to exist as we have implemented `IEventHandler`
})
}
public onMyEvent() {
// do stuff on that event
}
}
這需要手動設置,而內置的生命周期掛鈎(如ngOnInit
)則不需要,但這里的區別在於所有組件都需要ngOnInit
,而其中只有一些組件需要訂閱myEventSubject
。 正是這種選擇性阻止了體驗的“無縫”
你當然可以探索一個基礎 class 來讓你的工作組件稍微更“整潔”
export class BaseEventHandler implements IEventHandler {
constructor(public eventHandlerService: EventHandlerService) {}
ngOnInit() {
this.eventHandlerService.myEventSubject.subscribe({
next: () => this.onMyEvent() // guaranteed to exist as we have implemented `IEventHandler`
})
}
public onMyEvent() {
// do stuff on that event
}
}
export class MyComponent1 extends BaseEventHandler {
constructor(public eventHandlerService: EventHandlerService) {
super(eventHandlerService)
}
ngOnInit() {
super.ngOnInit();
}
}
export class MyComponent2 {
constructor() {}
}
但是與以前的實現相比似乎沒有什么好處,考慮到您仍然依賴於服務和對服務變量的選擇性訂閱(在本例中是BaseEventHandler
的選擇性擴展)
您還提到了ComponentRef
,即大概使用ViewChild
訪問組件實例並以如下方式調用相關方法:
@ViewChild(ChildComponent) childComponentRef: ComponentRef
this.childComponentRef.onMyEvent()
但是在這種情況下,事件的觀察者仍然必須駐留在各個組件中(在這種情況下是父組件而不是子組件)並且由於並非所有父組件都需要訂閱觀察者,您將再次實現這是使用選擇性訂閱與始終可用的掛鈎,例如ngOnInit()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.