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

您是否将您的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 中删除了它的用法😳

让我们谈谈升级到 Ionic 5 时的第三个重大变化。

如果您看到重大变更,您会看到@ionic/angular Event 已从 Ionic 5 中删除,他们说要使用ObservablesRedux作为替代方案。

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

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

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

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

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


↓↓↓ 以下代码来自替代 Ionic 5 中删除的事件

因此,让我们首先将以下 Angular 服务复制到您的 Ionic/Angular 代码中,创建一个服务类,你可以使用ionic g service events命令快速创建一个:

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

/**
 * 自定义事件服务,就像 Ionic 3 事件 https://ionicframework.com/docs/v3/api/util/Events/ 在 Ionic 5 中被删除。
 *
 * @author Shashank Agrawal
 */
@Injectable({
    providedIn: 'root'
})
export class Events {

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

    /**
     * 订阅主题并提供单个处理程序/观察者
     * @param topic 要订阅的主题名称
     * @param observer 发布更改时监听的观察者或回调函数
     *
     * @returns Subscription 您可以使用变量接收此函数的返回值,然后取消订阅时调用它的`unsubscribe`方法,以释放内存资源并防止内存泄漏
     */
    subscribe(topic: string, observer: (_: any) => void): Subscription {
        if (!this.channels[topic]) {
            // 您还可以使用 ReplaySubject 并产生一个结果
            this.channels[topic] = new Subject<any>();
        }
        return this.channels[topic].subscribe(observer);
    }

    /**
     * 向给定主题的订阅者发布一些数据
     * @param topic 要向其发送数据的主题的名称
     * @param data 以任何格式传递的数据
     */
    publish(topic: string, data?: any): void {
        const subject = this.channels[topic];
        if (!subject) {
            // 或者您可以为未来的订阅者创建一个新主题
            return;
        }
        subject.next(data);
    }

    /**
     * 当您确定您已完成该主题并且订阅者不再需要收听特定主题时,您可以使用此方法销毁该主题的可观察对象。
     * 销毁该主题的可观察对象(这将会在全局销毁,而不是针对一个可观察对象)
     * 如果只销毁一个可观察对象,在订阅时用变量接收实例,销毁时调用实例的 unsubscribe 方法即可
     * @param 要销毁的主题的名称
     */
    destroy(topic: string): null {
        const subject = this.channels[topic];
        if (!!subject) {
            subject.complete();
            delete this.channels[topic];
        }
        return null;
    }
}

1. 更改引入

更改之前

import {Events} from 'ionic-angular';

更改之后

import {Events} from '../your/path/to/service/events';

2. 更改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);
});

3. 更改publish方法

更改之前

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

更改之后

this.events.publish('foo:user:logged-out', {
    user: someUserInstance,
    time: new Date()
});

4. 更改Unsubscribe

const subscription = this.events.subscribe('user:foo:created', (data: any) => {
    // your logic
});

完成后,您可以这样做-

subscription.unsubscribe();

↑↑↑ 以上代码来自替代 Ionic 5 中删除的事件


虽然上面已经给出了这些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博客,destroy函数部分更改过(因为ES检查会报错),原文链接:https://medium.com/wizpanda/dealing-with-breaking-change-in-ionic-5-db3ba711dfcd#:~:text=If%20you%20see%20the%20Breaking,or%20Redux%20as%20an%20alternative.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容