处理 Ionic 5 中的重大变化:删除了Events,如何在ionic 5+版本中实现自定义Events用于旧版本的替代方案?

发布时间 2023-06-02 22:20:01作者: 豪杰i

您是否将您的Ionic应用程序升级到v5,而您的应用程序正在使用Events,它不再工作?

如果上述情况属实,那么您来对地方了。

先讲个小故事——

几天前,我看到一条来自离子团队的推文Ionic 5 已发布,在看到该推文 10 分钟后,我仅使用两个命令将我们的一个中型生产应用程序升级到 Ionic 5 和 Angular 9:

npm install @ionic/angular@latest @ionic/angular-toolkit@latest
ng update @angular/core @angular/cli

运行上述命令后,我验证了更改,提交了它,然后运行ionic serve但没有任何效果 ☹️

我原以为升级到 Ionic 5 会像将普通 Angular 应用程序升级到 Angular 9 一样顺利,但事实并非如此。所以我的转发有点不真实?

基本上,对于那个生产 Ionic 应用程序,我在升级到 Ionic 5 和 Angular 9 时遇到了三个问题(我花了一个小时来修复)。为了简洁起见,我将问题和解决方案链接发布到前两个问题:

  1. TypeScript 编译问题 https://stackoverflow.com/q/60182031/2405040
  2. Angular AOT 编译问题 https://stackoverflow.com/q/60182031/2405040
  3. Events在 Ionic 5 中删除了它的用法?

等等,什么是 Observables 和 redux???

不用担心,您可以谷歌它并了解它。有大量的博客文章和文章供您实现。但就目前而言,我们必须专注于将我们的应用程序升级到 Ionic 5。

为此,我们将使用 Subject,它是一种 Obersable

但是我不能重构我的代码那么多而且我不知道Observable?

不用担心。Wiz Panda相信#giveback 会帮助支持开源社区。

因此,让我们首先将以下 Angular 服务复制到您的 Ionic/Angular 代码中:

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

/**
 * A custom Events service just like Ionic 3 Events https://ionicframework.com/docs/v3/api/util/Events/ which got removed in Ionic 5.
 *
 * @author Shashank Agrawal
 */
@Injectable({
    providedIn: 'root'
})
export class Events {

    private channels: { [key: string]: Subject<any>; } = {};

    /**
     * Subscribe to a topic and provide a single handler/observer.
     * @param topic The name of the topic to subscribe to.
     * @param observer The observer or callback function to listen when changes are published.
     *
     * @returns Subscription from which you can unsubscribe to release memory resources and to prevent memory leak.
     */
    subscribe(topic: string, observer: (_: any) => void): Subscription {
        if (!this.channels[topic]) {
            // You can also use ReplaySubject with one concequence
            this.channels[topic] = new Subject<any>();
        }

        return this.channels[topic].subscribe(observer);
    }

    /**
     * Publish some data to the subscribers of the given topic.
     * @param topic The name of the topic to emit data to.
     * @param data data in any format to pass on.
     */
    publish(topic: string, data?: any): void {
        const subject = this.channels[topic];
        if (!subject) {
            // Or you can create a new subject for future subscribers
            return;
        }

        subject.next(data);
    }

    /**
     * When you are sure that you are done with the topic and the subscribers no longer needs to listen to a particular topic, you can
     * destroy the observable of the topic using this method.
     * @param topic The name of the topic to destroy.
     */
    destroy(topic: string): null {
        const subject = this.channels[topic];
        if (!subject) {
            return;
        }

        subject.complete();
        delete this.channels[topic];
    }
}
  1. 更改引入

更改之前

import {Events} from 'ionic-angular';

更改之后

import {Events} from '../your/path/to/service/events';
  1. 更改subscribe方法

更改之前

events.subscribe('user:created', (user, time) => {
    console.log('Welcome', user, 'at', time);
});

更改之后

this.events.subscribe('user:created', (data: any) => {
    console.log('Welcome', data.user, 'at', data.time);
});
  1. 更改publish方法

更改之前

this.events.publish('user:created', someUserInstance, Date.now());

更改之后

this.events.publish('foo:user:logged-out', {
    user: someUserInstance,
    time: new Date()
});
  1. 更改Unsubscribe
const subscription = this.events.subscribe('user:foo:created', (data: any) => {
    // your logic
});

完成后,您可以这样做-

subscription.unsubscribe();

虽然上面已经给出了这些Events步骤,但让我们运行这些步骤并通过将其与此处给出的原始 Ionic 3 进行比较来快速更改我们的代码https://ionicframework.com/docs/v3/api/util/Events/

a) 改变导入:

// 之前
import {Events} from 'ionic-angular';
// 之后
import {Events} from '../your/path/to/service/events';

b) 依赖注入没有变化

constructor(private events: Events) {}

c)subscribe方法的改变

// 之前
events.subscribe('user:created', (user, time) => {
    console.log('Welcome', user, 'at', time);
});
// 之后
this.events.subscribe('user:created', (data: any) => {
    console.log('Welcome', data.user, 'at', data.time);
});

基本上,您不能像以前那样获取多个数据。因此,您将在单个参数中获取数据。

d)publish方法的改变

// 之前
this.events.publish('user:created', someUserInstance, Date.now());
// 之后
this.events.publish('foo:user:logged-out', { 
    user: someUserInstance, 
    time: new Date () 
});

因此,之前您可以将多个参数传递给该publish方法,但现在您必须将它们作为对象传递。

(虽然,您仍然可以调整服务代码以接受相同格式)。

就是这样……

现在,您可以测试您的代码并查看是否一切正常。

快乐编码!

此文翻译自medium博客,原文链接:https://medium.com/wizpanda/dealing-with-breaking-change-in-ionic-5-db3ba711dfcd#:~:text=If%20you%20see%20the%20Breaking,or%20Redux%20as%20an%20alternative.