【问题标题】:How to emit an event from grandchildren to grandparent in modern angular?如何以现代角度发出从孙子到祖父母的事件?
【发布时间】:2019-06-15 09:23:04
【问题描述】:

如果我有多个级别的角度组件,我如何使用@Output 将事件从子级发送到祖父级?

祖父母:

<parent (handleClick)="grandmaHandleClick($event)">
<parent>
...
grandmaHandleClick(event) {
  console.log('grandma knows you clicked')
}

家长:

<child (handleClick)="handleClick($event)">
</child>

孩子:

<div (click)="onClick()">Click button
</div>
...
@Output() handleClick = new EventEmitter
onClick() {
  this.handleClick.emit('clicked a button')
}

我正在尝试使用它,以便 @Output 可以深入钻取一些组件,实现这一点的最佳方法是什么,您能提供示例吗?

【问题讨论】:

标签: javascript angular typescript events


【解决方案1】:

可能有两种方式:

  1. 使用@output:

祖父母

<parent (notifyGrandParent)="grandmaHandleClick($event)">
<parent>
...
grandmaHandleClick(event) {
  console.log('grandma knows you clicked')
}

家长

<child (handleClick)="childEvent($event)">
</child>

@Output() notifyGrandParent= new EventEmitter();
childEvent(event) {
  this.notifyGrandParent.emit('event')
}

Child 已在代码中正确实现,因此可以继续使用。

  1. 通过Service使用BehaviorSubject:有了这么多层次的嵌套,你实际上可以创建一些像EventService这样的服务,然后创建BehaviorSubject可以直接被GrandParent订阅。此外,为了使这个service 更具体的组件,您可以将此服务保存在一个module 中,该module 将包含其他3 个组件(GrandParent、Parent 和 Child)
export class EventService{

 private childClickedEvent = new BehaviorSubject<string>('');

  emitChildEvent(msg: string){
     this.childClickedEvent.next(msg)
  }

  childEventListner(){
     return this.childClickedEvent.asObservable();
   } 

}

然后在components:

子组件

export class ChildComponent{
   constructor(private evtSvc: EventService){}

   onClick(){
     this.evtSvc.emitChildEvent('clicked a button')
   }
}

祖父母

export class GrandComponent{
   constructor(private evtSvc: EventService){}

   ngOnInit(){
     this.evtSvc.childEventListner().subscribe(info =>{
         console.log(info); // here you get the message from Child component
      })
   }
}

请注意,通过@output 事件,您创建了组件的紧密耦合,因此创建了强依赖关系(parent-child-grandchild)。如果组件不可重用并且仅用于此目的而创建,那么@output 也将有意义,因为它将向任何新开发人员传达他们具有父子关系的消息。

创建一个传递数据的服务也会将数据暴露给其他组件,这些组件可以在constructor 中注入service

所以,应该做出相应的决定

【讨论】:

  • 在第一种方法中,@output 会不会在子组件上?
  • @user2167582:您已经在child component 中使用@Output() handleClick 正确处理了它,这就是我没有提及它的原因。让我也补充一下
  • 谢谢你,我做到了,它有效。在问这个问题时,我也很好奇是否有一种方法可以将(boundedEvent)组件向下传递,而不必添加处理程序方法来重新发射层次结构,似乎需要它。
  • @user2167582:如果它只是一级parentchild组件,您可以使用@Input并在child中使用ngOnChange来监控传递给@987654344的值的变化@。否则,如果是多级组件结构,可以再次使用BehaviorSubject
  • 这对我很有帮助。只是一个小细节......在原始帖子中有一行......&lt;div (click)="onClick"&gt;Click button&lt;/div&gt;onClick 应该是 onClick()。答案是,“Child 已在代码中正确实现,因此可以继续使用”——因此有人可能会感到困惑。
【解决方案2】:

使用rxjs/subject,可以同时是observable和observable。

用法:

  1. 在服务中创建主题属性:
import { Subject } from 'rxjs';

export class AuthService {
  loginAccures: Subject<boolean> = new Subject<boolean>();
}
  1. 当事件发生在子页面/组件使用时:
logout() {
  this.authService.loginAccures.next(false);
}
  1. 并订阅父页面/组件中的主题:
constructor(private authService: AuthService) {
  this.authService.loginAccures.subscribe((isLoggedIn: boolean) => {
    this.isLoggedIn = isLoggedIn;
  })
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 2023-01-07
    • 2017-11-14
    • 2018-09-04
    相关资源
    最近更新 更多