Angular 角度2:使用服务广播事件

Angular 角度2:使用服务广播事件,angular,service,eventemitter,Angular,Service,Eventemitter,我试图在一个组件中点击一个按钮,将焦点放在另一个组件上的一个元素上。(坦率地说,我不明白为什么这会如此复杂,但我还没有实现任何实际可行的更简单的方法。) 我正在使用一个服务。它不需要传递任何数据,除非发生了单击。我不确定监听组件是如何响应事件的 应用程序组件: <input type="text" name="username" /> import { Component, OnInit } from '@angular/core'; import { SkipToContent

我试图在一个组件中点击一个按钮,将焦点放在另一个组件上的一个元素上。(坦率地说,我不明白为什么这会如此复杂,但我还没有实现任何实际可行的更简单的方法。)

我正在使用一个服务。它不需要传递任何数据,除非发生了单击。我不确定监听组件是如何响应事件的

应用程序组件:

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


import { Component, OnInit } from '@angular/core';
import { SkipToContentService } from '../../../services/skip-to-content.service';

export class BaseLoginComponent implements OnInit {

    constructor(
        private skipToContent: SkipToContentService
        ) {
    }

    ngOnInit() {
        this.skipToContent.skipClicked.subscribe(
            console.log("!")
            // should put focus() on input
        );

    }
}
跳到主要内容

import { Component } from '@angular/core';
import { SkipToContentService } from './services/skip-to-content.service';


export class AppComponent {
    constructor(
        private skipToContent: SkipToContentService
    ) {}
    }

    skipLink() {
        this.skipToContent.setClicked();
    }

}
登录组件:

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


import { Component, OnInit } from '@angular/core';
import { SkipToContentService } from '../../../services/skip-to-content.service';

export class BaseLoginComponent implements OnInit {

    constructor(
        private skipToContent: SkipToContentService
        ) {
    }

    ngOnInit() {
        this.skipToContent.skipClicked.subscribe(
            console.log("!")
            // should put focus() on input
        );

    }
}

从“@angular/core”导入{Component,OnInit};
从“../../../services/skip到content.service”导入{SkipToContentService};
导出类BaseLoginComponent实现OnInit{
建造师(
私有skipToContent:SkipToContentService
) {
}
恩戈尼尼特(){
this.skipToContent.skipClicked.subscribe(
控制台日志(“!”)
//应该将focus()放在输入上
);
}
}
跳到content.service:

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

@Injectable()
export class SkipToContentService {

    skipClicked: EventEmitter<boolean> = new EventEmitter();


    constructor() {
    }

    setClicked() {
        console.log('clicked');
        this.skipClicked.emit();
    };
}
从'@angular/core'导入{Injectable,EventEmitter};
@可注射()
导出类SkipToContentService{
skipClicked:EventEmitter=新的EventEmitter();
构造函数(){
}
setClicked(){
console.log('clicked');
this.skipClicked.emit();
};
}

关于登录如何“听到”skipClicked事件,我在这里有点不知所措。

首先,使用
行为主体
而不是
事件发射器
。将
skipCliekd
的声明更改为以下内容:

skipClicked: BehaviorSubject<boolean> = new BehaviorSubject(false);
另外,将您的订阅更改为:

 this.skipToContent.skipClicked.subscribe( value => {
     if (value === true) {
         console.log("!"); 
         // should put focus() on input 
     }
 });

EventEmitter应仅在带有@Output指令的实际组件中使用。其他任何东西在将来都可能行不通。 对于儿童-家长沟通,最好使用主题或行为主题。这是一个来自角度引导的示例


windowClosed.next()
将发出事件

一些问题:1]“GeneratorNext不是函数”在SafeSubscriber.schedulerFn[as _next](event _emitter.ts:115)2]事件在页面加载时自动触发。i、 我得到的第一件事是“!”。3] 据我所知,next()不推荐使用emit()EventEmmiter,只在componentEventEmitter中使用,应该只在实际组件中使用,Angular component integration Guide建议使用共享服务,如另一个答案所示,因此,由于答案需要更新或误导他人,所以不应在服务中使用
EventEmitter
。使用共享服务来广播活动:是的,当我只需要这项服务来做一件事的时候,我也真的很难过。我该给它取什么名字呢?它是以组件命名的,还是以动作命名的,还是以动作类型命名的。我想你只需要看看什么对你有用。另一件需要记住的关键事情是,你可以将用于内部数据传输的服务组合起来。它们可以相互注入,如果您有一个包含5个不相关子项的复杂控件,则可以注入5个您想要的服务。我希望他们有一个比“服务”更好的名字
@Injectable()
export class MissionService {

  // Observable string sources
  private missionAnnouncedSource = new Subject<string>();
  private missionConfirmedSource = new Subject<string>();

  // Observable string streams
  missionAnnounced$ = this.missionAnnouncedSource.asObservable();
  missionConfirmed$ = this.missionConfirmedSource.asObservable();

  // Service message commands
  announceMission(mission: string) {
    this.missionAnnouncedSource.next(mission);
  }

  confirmMission(astronaut: string) {
    this.missionConfirmedSource.next(astronaut);
  }
}
windowClosed = new Subject<void>();