【问题标题】:How to emit event in router-outlet in Angular2如何在Angular2的路由器插座中发出事件
【发布时间】:2016-11-18 12:13:47
【问题描述】:

我有主 appComponent 和

<div class="appComponent">
<div class="row nav navbar">
    <div class="col-sm-8 text-left nav logo">Manacola</div>
    <button class="col-sm-1  col-sm-offset-1  btn btn-primary openGraph" (click)="openGraph()">Graph</button>
    <button class="col-sm-1   btn btn-primary openGraph" *ngIf="loggedIn" (click)="logout()">Logout</button>
</div>
<router-outlet ></router-outlet>

我想从另一个登录组件发出数据。 关键是当我按下loginComponent 中的“登录”按钮时,我希望*ngIf="loggedIn"appComponent 中设置为“true”。 有这样的工作会很好:

<router-outlet (isLogged) = 'loggedIn = $event' ></router-outlet>   

【问题讨论】:

    标签: angular routing


    【解决方案1】:

    这是一个很棒的小实用服务,用于在 angular2 应用程序中代理事件。请注意,您实际上应该只使用这种类型的事件代理在解耦组件之间进行通信(例如在 router-outlet 的父级和子级之间)

    示例:

    ....
    import { EventBrokerService, IEventListener } "EventBrokerService";
    
    @Component({
        selector: "my-listening-component",
        template: `
            <div *ngIf="indicator">I am On!</div>
            <div *ngIf="!indicator">I am Off!</div>
        `
    })
    @Injectable()
    export class MyListeningComponent implements OnDestroy {
        public indicator: boolean = false;
        private _myEventListener: IEventListener;
        constructor(private _eventBroker: EventBrokerService) {
            this._myEventListener = _eventBroker.listen<boolean>("my-event",(value:boolean)=>{
                 this.indicator = value;
            });
        }
        public ngOnDestroy() {
            this._myEventListener.ignore();
        }
    }
    
    @Component({
        selector: "my-sending-component",
        template: `
            <button (click)="canYouHearMe(true)>Turn me on</Button>
            <button (click)="canYouHearMe(false)>Turn me off</Button>
        `
    })
    @Injectable()
    export class MySendingComponent {
        constructor(private _eventBroker: EventBrokerService) {
        }
        public canYouHearMe(value:boolean) {
            _eventBroker.emit<boolean>("my-event",value);
        }
    }
    

    EventBrokerService.ts 文件:

    import { Injectable } from '@angular/core';
    import { Subscription } from 'rxjs';
    import { Subject }    from 'rxjs';
    
    interface IEventListener {
        ignore() : void;
    }
    interface IBrokeredEventBase {
        name:string;
        emit( data: any ): void;
        listen( next: (data: any) => void ): IEventListener;
    }
    interface IBrokeredEvent<T> extends IBrokeredEventBase  {
        emit( data: any ): void;
        listen( next: (data: any) => void ): IEventListener;
    }
    class EventListener implements IEventListener {
        constructor( private _subscription: Subscription ) {
        }
        public ignore() : void {
            this._subscription.unsubscribe();
        }
    }
    
    class BrokeredEvent<T> implements IBrokeredEvent<T> {
        private _subject: Subject<T>;
        constructor( public name: string ) {
            this._subject = new Subject<T>();
        }
        public emit( data: T ): void {
            this._subject.next(data);
        }
        public listen(next: (value: T) => void): IEventListener {
            return new EventListener(this._subject.subscribe( next ));
        }
    }
    @Injectable()
    export class EventBrokerService {
        private _events: { [name: string]: IBrokeredEventBase };
        constructor() {
            this._events = {};
        }
        public register<T>(eventName: string ) : BrokeredEvent<T> {
            var event = this._events[eventName];
            if ( typeof event === 'undefined' ) {
                event = this._events[eventName] = new BrokeredEvent<T>(eventName);
            }
            return event as BrokeredEvent<T>;
        }
        public listen<T>(eventName: string, next: (value: T) => void) : IEventListener {
            return this.register<T>(eventName).listen(next);
        }
        public emit<T>(eventName: string, data: T) : void {
            return this.register<T>(eventName).emit(data);
        }
    }
    

    不要忘记在 angular2 模块中将 EventBrokerService 注册为提供程序。

    【讨论】:

    • interface IEventListener 需要导出,否则MyListeningComponent 将无法看到它
    • IBrokeredEventBase被IBrokeredEvent扩展的目的是什么,为什么第二个接口方便?
    【解决方案2】:

    您可以在路由器出口处渲染的组件中定义@Output 事件发射器。 如下定义路由器出口。

    *.html
    <router-outlet (activate)="onActivate($event)"></router-outlet>
    

    在您的组件中,您可以这样做。

    onActivate(elementRef) {
        elementRef.<the @Output eventEmitter>.subscribe(event => {
            console.log(event);
        });
    }
    

    这样你可以将事件发送到渲染路由器出口的组件。这是因为@Output 事件发射器是事件流,您可以订阅这些事件。

    【讨论】:

    • 您好,抱歉,但是当您路由到没有该 eventEmitter 的组件时会发生什么?
    • 不错的发现。 @ALGDB 如果您的组件没有输出,则不会发出任何内容,对。您只是订阅了向 RouterOutlet 发出的事件,这是从 Outlet 中使用的组件发出的任何东西。你有点捎带了正在发出的激活事件。这很聪明。
    • 此功能是否特定于某个 Angular 版本?这种语法对我不起作用。
    • (activate) 与按下登录按钮有什么关系? (activate) 只会在路由改变时触发,不是吗?
    • @RonInbar,(activate) 在路由匹配时触发,因此组件的目标被加载(在 内),(deactivate) 在路由不再匹配时触发组件目标,您可以使用这两个事件修改字段isLoggedIn
    猜你喜欢
    • 2017-04-29
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 2016-04-23
    • 2020-01-13
    • 2017-03-21
    • 1970-01-01
    相关资源
    最近更新 更多