【问题标题】:Child listens for parent event in Angular 2孩子在Angular 2中监听父事件
【发布时间】:2016-10-07 05:22:10
【问题描述】:

在 Angular 文档中,有一个关于监听来自父母的孩子事件的主题。没关系。但我的目的是相反的!在我的应用程序中有一个“admin.component”,其中包含管理页面的布局视图(侧边栏菜单、任务栏、状态等)。 在这个父组件中,我配置了路由器系统以更改管理员其他页面之间的主视图。 问题是更改后保存内容,用户单击任务栏中的保存按钮(放置在 admin.component 中),子组件必须侦听该单击事件才能保存人员。

【问题讨论】:

  • 听起来最好的做法是使用服务和可观察的调度事件。
  • 你的问题和这个问题没有太大的不同:stackoverflow.com/questions/35560860/…
  • @freethebees 也许解决方案是一样的,但问题的形式不同,我的目的是找到解决这种情况的最佳方法。
  • 我们不会为传递给子组件的单个事件设置服务。

标签: javascript typescript angular rxjs eventemitter


【解决方案1】:

对于那些收到Cannot read property 'notifyMe' of undefined的人

尝试调用ngAfterViewInit() 内部的方法,而不是ngOnInit()

【讨论】:

    【解决方案2】:

    为了后代,我只是想提一下对此的更常规解决方案:只需获取对 ViewChild 的引用,然后直接调用其中一个方法。

    @Component({
      selector: 'app-child'
    })
    export class ChildComponent {
    
      notifyMe() {
        console.log('Event Fired');
      }
    }
    
    @Component({
      selector: 'app-parent',
      template: `<app-child #child></app-child>`
    })
    export class ParentComponent {
    
      @ViewChild('child')
      private child: ChildComponent;
    
      ngOnInit() {
        this.child.notifyMe();
      }
    }
    

    【讨论】:

    • 一进入父组件就崩溃了...Cannot read property 'notifyMe' of undefined.
    • 与@ThierryTemplier 的某种更专业的感觉解决方案相比,选择了这个非常简单的解决方案(请参阅我的评论)。
    • @BernoulliIT 你说得很好。我想在一天结束时,他们完成了大致相同的事情。我的解决方案使用更少的代码。他的解决方案意味着父组件不必注入子组件来发送消息。 RXJS 很棒,但我确实经常看到在 Angular 项目中过度使用它。人们认为这是“银弹”之类的。它实际上可以使事情变得比他们需要的复杂得多。查看他在ngOnDestroy() 方法中的评论。就我而言,这太模糊了。恕我直言,这只是一个等待发生的错误。
    • “看看他在 ngOnDestroy() 方法中的评论。”我认为这正是我在尝试这种方法时“遭受”的痛苦,然后我被卡住了,没有太多时间进一步调查(对于我从事的商业项目)。虽然它“伤害”了我的职业心;)
    • 感谢@StephenPaul,对我来说Parent Calls a Viewchild 方法很好,但您的回答帮助我实现了自己的命运!
    【解决方案3】:

    如果我正确理解了这个问题,这里可能会采用更简单的方法。假设 --

    • OP 在父组件中有一个保存按钮
    • 需要保存的数据在子组件中
    • 子组件可能需要的所有其他数据都可以从服务中访问

    在父组件中

    <button type="button" (click)="prop1=!prop1">Save Button</button>
    <app-child-component [setProp]='prop1'></app-child-component>
    

    在孩子身上..

    prop1:boolean;
      @Input()
      set setProp(p: boolean) {
        // -- perform save function here
    }
    

    这只是将按钮点击发送到子组件。从那里子组件可以独立保存数据。

    编辑:如果来自父模板的数据也需要与按钮单击一起传递,那么这种方法也可以。如果是这种情况,请告诉我,我会更新代码示例。

    【讨论】:

      【解决方案4】:

      我认为此文档可能对您有所帮助:

      事实上,您可以利用父级提供给其子级的可观察/主题。类似的东西:

      @Component({
        (...)
        template: `
          <child [parentSubject]="parentSubject"></child>
        `,
        directives: [ ChildComponent ]
      })
      export class ParentComponent {
        parentSubject:Subject<any> = new Subject();
      
        notifyChildren() {
          this.parentSubject.next('some value');
        }
      }
      

      子组件可以简单地订阅这个主题:

      @Component({
        (...)
      })
      export class ChildComponent {
        @Input()
        parentSubject:Subject<any>;
      
        ngOnInit() {
          this.parentSubject.subscribe(event => {
            // called when the notifyChildren method is
            // called in the parent component
          });
        }
      
        ngOnDestroy() {
          // needed if child gets re-created (eg on some model changes)
          // note that subsequent subscriptions on the same subject will fail
          // so the parent has to re-create parentSubject on changes
          this.parentSubject.unsubscribe();
        }
      
      }
      

      否则,您可以以类似的方式利用包含此类主题的共享服务...

      【讨论】:

      • 除非父组件从 ngInit 中广播下一个值,否则我的子组件中的回调将不会运行。为什么会这样?
      • 与ViewChild相比,使用这种方法有什么优势吗?
      • 虽然它看起来更专业,但在我的情况下尝试了几个小时后,在添加/删除子元素(因此取消订阅该主题)时,我无法摆脱 UnsubscribeErrors 的麻烦。因此,通过 TimeBoxing,我得到了@StephenPaul 更直接的答案。无论如何,感谢您的回答,可能我现在对 rxjs 库的理解还不够好,无法完全理解它并对您的示例进行正确的(额外)调整以使其完美运行。
      猜你喜欢
      • 2019-11-21
      • 2021-11-02
      • 1970-01-01
      • 2017-07-09
      • 1970-01-01
      • 2016-06-25
      • 2018-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多