可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I understand Ionic events will be deprecated in next version. 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:
this.events.publish('form:refresh');
How would I do the above using angular observables?
回答1:
you can use rxjs Subject for that so first create a common service eg.
@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
this.subscription.unsubscribe()
回答2:
USER EVENTS AS YOU USED TO IN IONIC 3.
You just have to import this service/provider in a page you want to use it.
Reference
https://git.furworks.de/opensourcemirror/Ionic/commit/e5f2a18230f3ca3017f0302fb57ef275d0f63a8b
i
mport { 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;
}
});
}
}
回答3:
You can create a service with a BehaviorSubject
and you can pass data and subscribe to it wherever you want. In your case pass in the child and subscribe in the parent component.
回答4:
// make service using : ionic g service events
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
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
})
}
回答5:
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. 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.
回答6:
This can be dealt with by using an Events service as pointed out in this medium post Dealing with breaking change in Ionic 5
The author illustrates how one can refactor code with minimal ease and maintain the flow.