简体   繁体   English

离子事件替换为 Angular Observables

[英]Ionic Events replace with Angular Observables

I understand Ionic events will be deprecated in next version.我了解 Ionic 事件将在下一个版本中被弃用。 Currently I use events to executes functions in my parent page from sub components.目前,我使用事件从子组件执行父页面中的功能。 Here is an example:这是一个例子:

In my main page it subscribes to the event to refresh:在我的主页中,它订阅了要刷新的事件:

constructor(){
  this.eventFormRefresh = (obj) => {
    this.fetch(obj.isReset);
  };
  this.events.subscribe('form:refresh', this.eventFormRefresh);
}

ngOnDestroy(): void {
  this.events.unsubscribe('form:refresh', this.eventFormRefresh);
}

In a subcomponent I activate the refresh by publishing the 'form:refresh' event as so:在子组件中,我通过发布 'form:refresh' 事件来激活刷新,如下所示:

this.events.publish('form:refresh');

How would I do the above using angular observables?我将如何使用 angular observables 执行上述操作?

you can use rxjs Subject for that so first create a common service eg.您可以为此使用rxjs 主题,因此首先创建一个公共服务,例如。

@Injectable()
export class EventService{
  private formRefreshAnnouncedSource = new Subject();
  formRefreshSource$ = this.formRefreshAnnouncedSource.asObservable();

  publishFormRefresh(){
    this.formRefreshAnnouncedSource.next()
  }

}

then publish like然后像这样发布

this.eventService.publishFormRefresh();

and subscribe in some componenet并订阅一些组件

this.subscription = this.eventService.formRefreshSource$.subscribe(data => {
  //do something here
});

and cancel subscription on ngOnDestroy取消对 ngOnDestroy 的订阅

this.subscription.unsubscribe()

USER EVENTS AS YOU ARE USED TO IN IONIC 3. You just have to import this service/provider in a page you want to use it. IONIC 3 中的用户事件。您只需在要使用的页面中导入此服务/提供者即可。 Reference https://git.furworks.de/opensourcemirror/Ionic/commit/e5f2a18230f3ca3017f0302fb57ef275d0f63a8b参考https://git.furworks.de/opensourcemirror/Ionic/commit/e5f2a18230f3ca3017f0302fb57ef275d0f63a8b

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

export type EventHandler = (...args: any[]) => any;
@Injectable({
  providedIn: 'root',
})
export class Events {
  private c = new Map<string, EventHandler[]>();

  constructor() {
  //   console.warn(`[DEPRECATION][Events]: The Events provider is deprecated, and it will be removed in the next major release.
  // - Use "Observables" for a similar pub/sub architecture: https://angular.io/guide/observables
  // - Use "Redux" for advanced state management: https://ngrx.io`);
  }
  /**
   * Subscribe to an event topic. Events that get posted to that topic will trigger the provided handler.
   *
   * @param topic the topic to subscribe to
   * @param handler the event handler
   */
  subscribe(topic: any, ...handlers: EventHandler[]) {
    let topics = this.c.get(topic);
    if (!topics) {
      this.c.set(topic, topics = []);
    }
    topics.push(...handlers);
  }

  /**
   * Unsubscribe from the given topic. Your handler will no longer receive events published to this topic.
   *
   * @param topic the topic to unsubscribe from
   * @param handler the event handler
   *
   * @return true if a handler was removed
   */
  unsubscribe(topic: string, handler?: EventHandler): boolean {
    if (!handler) {
      return this.c.delete(topic);
    }

    const topics = this.c.get(topic);
    if (!topics) {
      return false;
    }

    // We need to find and remove a specific handler
    const index = topics.indexOf(handler);

    if (index < 0) {
      // Wasn't found, wasn't removed
      return false;
    }
    topics.splice(index, 1);
    if (topics.length === 0) {
      this.c.delete(topic);
    }
    return true;
  }

  /**
   * Publish an event to the given topic.
   *
   * @param topic the topic to publish to
   * @param eventData the data to send as the event
   */
  publish(topic: string, ...args: any[]): any[] | null {
    const topics = this.c.get(topic);
    if (!topics) {
      return null;
    }
    return topics.map(handler => {
      try {
        return handler(...args);
      } catch (e) {
        console.error(e);
        return null;
      }
    });
  }
}

// make service using: ionic g service events // 使用: ionic g 服务事件创建服务

    import { Injectable } from '@angular/core';
    import { Subject } from 'rxjs';

    @Injectable({
    providedIn: 'root'
     })

     export class EventsService {

     private refreshData=new Subject();

     constructor() {};

     refreshData= this.refreshDatasObservable();

     refresh(message){
     this.refreshDatanext(message)
     }

   }

in app.module.ts在 app.module.ts

      import {EventsService} from './service/vents.service'; // add it to   provider 

       providers:[....
               EventsService
                ....
                ]

in your desired page subscribe and call like this在您想要的页面中订阅并像这样调用

      import {EventsService} from './service/vents.service'; //import service                                   
          constructor(private eventsService:EventsService){

           //for refreshing or publishing
           this.eventsService.refresh('i am data');

          //for subscribing to change
          this.eventsService.refreshChatData$.subscribe(data=>{
            //do something
            })

           }

You can create a service with a BehaviorSubject and you can pass data and subscribe to it wherever you want.您可以使用BehaviorSubject创建服务,并且可以传递数据并在任何您想要的地方订阅它。 In your case pass in the child and subscribe in the parent component.在您的情况下,传入子组件并订阅父组件。

For anyone else finding this in the same setup I was in, here's another possible route.对于在与我相同的设置中发现此问题的其他人,这是另一种可能的路线。 We're looking at going from Ionic V3 -> V4 and know we have some headaches in store.我们正在考虑从 Ionic V3 -> V4 开始,并且知道我们有一些令人头疼的问题。 One being events deprecated.一个是不推荐使用的事件。 I decided to look how the ionic-angular implementation of events was set up, and realized I kind of liked it.我决定看看事件的离子角度实现是如何设置的,并意识到我有点喜欢它。 I made a service mimicking their implementation, hoping that replacing the ionic-angular Events later will be easier.我做了一个模仿他们实现的服务,希望以后替换离子角事件会更容易。

@Injectable()
export class Events {
    private _channels: { [key: string]: ((...args: any[]) => void)[] } = {};
    public subscribe(topic: string, handler: (...args: any[]) => void) {
        if (!this._channels[topic]) {
            this._channels[topic] = [];
        }
        this._channels[topic].push(handler);
    }
    public publish(topic: string, ...args: any[]) {
        if (this._channels[topic] && this._channels[topic].length) {
            this._channels[topic].forEach(handler => handler(...args));
        }
    }
    public unsubscribe(topic: string, handler: ((...args: any[]) => void) = null) {
        if (!handler) {
            delete this._channels[topic];
        }
        const index = this._channels[topic].indexOf(handler);
        if (index > 0) {
            this._channels[topic].splice(index, 1);
        }
        if (!this._channels[topic].length) {
            delete this._channels[topic];
        }
    }
}

I know this doesn't use Observables, but wanted to offer a different solution for anyone else hoping for a drop-in fix for ionic-angular/events I simplified / removed some of their code, if there's any concerns let me know.我知道这不使用 Observables,但想为其他任何人提供不同的解决方案,希望为我简化/删除了他们的一些代码的 ionic-angular/events 提供直接修复,如果有任何问题请告诉我。

This can be dealt with by using an Events service as pointed out in this medium post Dealing with breaking change in Ionic 5这可以通过使用事件服务来处理,正如这篇中篇文章处理 Ionic 5 中的重大变化中所指出的那样

The author illustrates how one can refactor code with minimal ease and maintain the flow.作者说明了如何以最简单的方式重构代码并保持流程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM