【问题标题】:Angular 2: emitter listener between componentsAngular 2:组件之间的发射器监听器
【发布时间】:2018-01-08 14:59:56
【问题描述】:

我正在制作“跳转到内容”链接。链接位于 app.component 中,内容与目标一起位于 login.component 中。

我试过several methods,但都没有成功。所以现在我正在尝试发射器/监听器:

app.component (emitter):

import { Component, Output, EventEmitter} from '@angular/core';

export class AppComponent {

    @Output() skipToCtrl: EventEmitter<any> = new EventEmitter();

    skipLink() {
        this.skipToCtrl.emit();
    }
}

<a href="#content-start" (click)="skipLink()">Skip to main content</a>

login.component(监听器):

<input type="text" #firstControl name="username" />

不知道 login 如何从 login 中订阅事件。我不断发现文章说这样做How to subscribe to an event on a service in Angular2?,但没有文章描述如何做到这一点。

【问题讨论】:

  • 我认为您对来自 Angular 1 的事件感到困惑。
  • 那么,混淆的是 Angular 2 文章。我很乐意接受教育。我还没有找到一篇文章来说明一个组件中的按钮如何触发另一个组件中的效果。

标签: angular eventemitter


【解决方案1】:

事件发射器用于将输出添加到模板中。使用圆括号() 绑定到事件。

当你创建一个组件时:

@Component({...})
public export FooComponent {
   @Output() name: EventEmitter = new EventEmitter<string>();
}

上面的组件现在有一个属性,可以在另一个模板中与()括号一起使用。

在另一个模板中:

 <foo (name)="// code here //"></foo>

当事件发出时(通过调用this.name.emit("value")),Angular 会执行上面的“code here”表达式。 emit 函数采用单个参数,该参数作为 $event 变量传递给表达式。

要让另一个组件接收这些事件是使用另一个组件模板中的表达式。

让我们创建一个Bar 组件

@Component({...})
export class BarComponent {
    public setName(value:string) {
        console.log(value); // will output "chicken"
    }
}

上面的组件有这个模板:

<foo (name)="setName($event)"></foo>

现在在Foo 组件中我们发出一个值。

@Component({...})
public export FooComponent implements OnInit {
   @Output() name: EventEmitter = new EventEmitter<string>();

   public ngOnInit() {
       this.name.emit("chicken");
   }
}

这会通过模板表达式创建从Foo 组件到Bar 组件的单向通信。

【讨论】:

  • Foo 是它自己的组件。我不能把它放在酒吧里。如果有的话,bar(登录)实际上是 foo(应用程序)的子集。
  • 你不是在我的回答上说他们不是亲子关系吗?似乎它们是,就像我在回答中所说的那样,你已经把它倒过来了。在你掌握它的适用性之前,你永远不会在这个问题上得到一个绿色方块。你根本不需要 eventEmitters。
  • 正确,在 Angular 1 中,您可以向上或向下广播范围树的事件。 Angular 2 中不存在该功能。事件纯粹是模板特定的功能。我真的不明白你想在你的问题中解决什么问题。为什么链接不能直接用[routerLink]去内容?
【解决方案2】:

在login.component中,你可以写

<input type="text" #firstControl (skipToCtrl)="callsomemethod($event)" name="username" />

【讨论】:

【解决方案3】:

您将事件发射器放在了错误的组件中。事件发射器用于子 -> 父通信。所以你可能想把它放在你的登录组件中,如果你想让它做任何事情。

login.component.ts

 export class LoginComponent {
     @Output() skipToCtrl: EventEmitter<any> = new EventEmitter();
     emitSkipEvent(): void {
         this.skipToCtrl.emit(true);
     }
  }

app.component.html

 <login-component (skipToCtrl)="skipLink()">

我的解决方案有一个问题,该事件永远不会发出,因为我从不调用 loginComponent.emitSkipEvent,我不认为 EventEmitter 行为是您想要的,因为您想将数据从父级传递到登录组件。您可能希望在您的登录组件上放置一个 @Input 参数并实现 onChanges 来处理该行为。更好的答案:

 import {OnChanges} from '@angular/core'
 export class LoginComponent implements OnChanges {
     @Input() skipToCtrl: boolean;
     ngOnChanges(){
         if(skipToCtrl){
             // handle login component behavior changes here. Looks like you want to focus on the input
             document.querySelector('input').focus();
         }
      }
}

然后在你的 app.component.ts 中创建一个布尔变量来切换

 linkClicked:boolean;

然后在您的 app.component.html 中,您可以更改点击行为并将 linkClicked 绑定到您的登录组件的 skipToCtrl 布尔值:

<a href="#content-start" (click)="linkClicked = true">Skip to main content</a>
<login-component [skipToCtrl]='linkClicked'>

现在,当您单击链接时,它将被传递到登录组件,并且 OnChanges 逻辑将触发。

【讨论】:

  • 它们只是两个组件。一个有一个“跳转到内容”的链接,另一个有一些内容,其中包含我想要关注的控件。就这样。没有父子关系。
  • 你确定吗?您的应用程序组件和登录组件是否有两个单独的应用程序?我对此表示怀疑,如果您这样做,请将您如何在问题中呈现组件。他们很可能有某种关系。通常,您的应用程序组件是所有组件的最高父级...但如果您很难得出这个结论,那么我无能为力。
  • 不是两个独立的应用程序,只是两个组件。我实际上并不知道它们之间的关系,因为我没有构建结构。我知道登录 HTML 内容嵌套在应用程序 HTML 包装器中。我不知道中间是否还有其他层。
  • 我用'implements OnChanges'尝试了你的方法,但它抱怨登录错误地实现了接口。当我试图修复它时,它只是告诉我下一层错误地实现了接口。
  • 我刚刚注意到我在 on changes 函数中忘记了一个右括号(已在答案中修复它),尽管您的 IDE 可能警告过您并且可能您已修复它。什么是抱怨,它告诉你什么?你有工具声明吗?如果您将 ngOnChanges() 更改为空白函数,它会抱怨吗?
【解决方案4】:

100% 工作!!!!它基本上是一个使用 Javascript 的补丁:

制作一个隐藏的输入元素,您需要在其中调用组件(在您的情况下为 app.component)

<input type="hidden" id="getdata" (click)="Mydata();">

这里 Mydata 将在 app.component 中起作用

并使用javascript从其他组件(登录)调用/单击此:

document.getElementById('getdata').click();

【讨论】:

    猜你喜欢
    • 2016-06-25
    • 1970-01-01
    • 2018-06-01
    • 2018-04-15
    • 2019-10-23
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多