问题 角度2:使用服务来广播事件


我试图在一个组件中单击一个按钮,将焦点放在另一个组件上的元素上。 (坦率地说,我不明白为什么它必须如此复杂,但我无法实现任何实际工作的简单方法。)

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

app.component:

跳到主要内容

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
        );

    }
}

跳跃到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();
    };
}

关于登录将如何“听到”skipClicked事件,我在这里有点迷失。


3290
2017-08-01 20:02


起源

你不应该使用 EventEmitter 在您的服务中 stackoverflow.com/questions/36076700/...。并使用共享服务来广播事件: angular.io/guide/... - eko


答案:


只需在setClicked()方法中进行一些小改动:

this.skipClicked.next(true);

代替 this.skipClicked.emit();

将您的订阅更改为:

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

这将解决您的问题。


8
2017-08-01 20:07



一些问题:1]“generatorOrNext不是函数”在SafeSubscriber.schedulerFn [as _next](event_emitter.ts:115)2]事件在pageload上自动触发。即我得到的第一件事是'! ”。 3]据我所知,next()已被弃用,有利于emit() - DaveC426913
我看到一个错误,检查我的更新答案 - Faisal
谢谢。这样可行。现在有半个解决方案。 - DaveC426913
EventEmmiter,仅用于组件 - Ricardo D. Quiroga
完美,像魅力一样工作 - AhammadaliPK


EventEmitter只能在具有@Output指令的实际组件中使用。其他任何东西将来都可能无效。

对于子父通信,最好使用Subject或BehaviorSubject。这是角度指南的一个例子。

https://angular.io/guide/component-interaction

@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);
  }
}

2
2018-02-08 23:14



是的,当我只需要服务来做一件事时,我真的很难过。我甚至将它命名为什么?是以组件命名,还是为操作命名,还是为操作类型命名。我想你只需看看哪些对你有用。 - Simon_Weaver
要记住的另一个关键事项是,您可以组合用于内部数据传输的服务。他们可以互相注入,如果你有5个不相关的孩子,你可以注入5个你需要的服务。我希望他们有一个比'服务'更好的名字 - Simon_Weaver