打字稿和多个类
Posted
技术标签:
【中文标题】打字稿和多个类【英文标题】:Typescript and multiple classes 【发布时间】:2017-08-19 03:29:49 【问题描述】:我有一个组件类EventSchedulePage
。它扩展了HandleStorageService
abstract
类,如下所示。你可以看到这个子类上有一个名为showInvalidTokenAlert()
的方法。我必须分别调用这个方法并且每个组件(此方法向用户提供基于令牌的错误消息)。那么您能告诉我如何实现或重新设计我的类以适应这种情况吗?因为我不喜欢将showInvalidTokenAlert()
放在每个组件上。我想将该方法的实现保留在一个地方。
子类
export class EventSchedulePage extends HandleStorageService
constructor()
super();
showInvalidTokenAlert()
//show alert
抽象类
export abstract class HandleStorageService
result: string = '';
constructor()
【问题讨论】:
那你为什么不把showInvalidTokenAlert
放到HandleStorageService
呢?
该服务仅用于处理与存储相关的事情。这就是原因。@NitzanTomer
是 ionic 2 吗?如果是这样,您可以只注入具有该功能的提供程序..
Hmm.. 我试图找到一个基于 TS 的解决方案。但似乎唯一的解决方案是基于提供程序的注入。我会尝试。同时,你也可以回答这个问题。 @suraj
【参考方案1】:
您可以使用showInvalidTokenAlert()
函数创建一个单独的提供程序类
@Injectable()
export class AlertProvider
constructor()
showInvalidTokenAlert()
//...
在 app.module.ts 中将其设置为提供者,以防您需要作为单例
@ngModule(
//...
providers:[
AlertProvider,
//..
]
)
注入您需要的任何组件。
export class EventSchedulePage extends HandleStorageService
constructor(private alertProvider:AlertProvider)
super();
//call this.alertProvider.showInvalidTokenAlert()
【讨论】:
我不能像这样在AlertProvider
中使用public navCtrl: NavController
吗? constructor(public alertCtrl: AlertController, public navCtrl: NavController)
.它给出了这个错误Error: Uncaught (in promise): Error: Error in ./MyApp class MyApp - inline template:0:0 caused by: No provider for NavController! Error: DI Error
.你知道为什么吗?
github.com/driftyco/ionic/issues/9581 似乎是设计使然...
尝试在构造函数中使用@Inject(NavController) navController: NavController
hmm.. 似乎是反模式,不是吗?我的意思是使用服务层来处理 UI 相关的事情?这就是为什么我尝试基于 TS 获得解决方案。您对此有何看法?
看起来是对的。我不建议这样做,因为您已经想扩展其他一些类了。“该服务仅用于处理与存储相关的事情。这就是原因。”您可以使用该方法并将 HandleStorageService 作为提供者..【参考方案2】:
您可以创建一个BasePage
,并将所有共享代码放在那里。
import Component, Injector from '@angular/core';
import AlertController, ... from 'ionic-angular';
@Component( selector: '', template: '<span></span>' )
export class BasePage
private _alertCtrl: AlertController;
private _toastCtrl: ToastController;
constructor(public injector: Injector)
// Get methods used to obtain instances from the injector just once
// ----------------------------------------------------------------
// AlertController
public get alertCtrl(): AlertController
if (!this._alertCtrl)
this._alertCtrl = this.injector.get(AlertController);
return this._alertCtrl;
// ToastController
public get toastCtrl(): ToastController
if (!this._toastCtrl)
this._toastCtrl = this.injector.get(ToastController);
return this._toastCtrl;
// ...
// Helper methods
// ----------------------------------------------------------------
public showAlertMessage(message: string): void
let alert = this.alertCtrl.create( ... );
alert.present();
public showToastMessage(message: string): void
let toast = this.toastCtrl.create( ... );
toast.onDidDismiss(() =>
console.log('Dismissed toast');
);
toast.present();
关键是BasePage
从子类接收注入器的实例,因此您可以从中获取您需要的任何实例(例如您需要显示警报消息的AlertController
实例)。通过使用 get 方法,每个实例只会从注入器中获取一次。
然后在您应用的所有页面中:
import Component, Injector from '@angular/core';
import BasePage from '../path/to/base';
@Component(
selector: 'page-home',
templateUrl: 'home.html'
)
export class HomePage extends BasePage
constructor(public injector: Injector)
super(injector);
public someMethod(): void
// You can use the methods from the BasePage!
this.showAlertMessage('Your message...');
public someOtherMethod(): void
this.showToastMessage('Another message');
这种方式超级容易添加一些辅助方法。
【讨论】:
我的问题是我已经在使用abstract
基类号(即HandleStorageService
)?那是用于处理与存储相关的方法。那么如何在 TS 上扩展 2 个类?
将逻辑从HandleStorageService
移动到BasePage
怎么样?毕竟它也可以被认为是一个助手......
@Sampath 我已经编辑了答案以解决该问题,并向您展示在何处包含该方法。关于注入器,请记住,在 Angular 2 应用程序中,不仅有一个 single 注入器,而且还有一个层次结构的注入器(每个组件都有自己的注入器),因此我们需要将该实例发送到 BasePage 以能够使用正确的 AlertCtrl、ToastCtrl 等实例(如果我们不这样做,当您尝试使用 alertCtrl 显示消息时,它可能会使用不同的 alertCtrl 实例,并且可以在某些其他组件 - 或我们使用 Ionic 时的页面 -)
很好的例子。顺便提一下,对于 ionic 4,我们需要 async/await async showAlertMessage(message: string) let alert = await this.alertCtrl.create(...); alert.present();
这是一个很棒的解决方案,非常感谢您发布它。我做了很多搜索才能找到这个,这比偷偷摸摸的服务要好得多。【参考方案3】:
hmm.. 似乎是反模式不是吗?我的意思是使用服务层来处理 UI相关的东西?这就是为什么我试图根据 TS.你对此有何看法? – Sampath
在控制器中处理它肯定更像 MVCS(模型-视图-控制器-服务)。但那是widely taken approach。
如果你想去,@suraj's answer 是我个人的推荐。
在控制器上处理警报当然是可能的。继续阅读。
event-schedule-page.service.ts
export class EventSchedulePage extends HandleStorageService
// ...
foo()
if (!bar)
throw new Error('Something went wrong.');
// ...
home.controller.ts
export class HomeController
// ...
foo()
try
eventSchedulePageService.foo();
catch (error)
window.alert(error); // Handle and UI display the error on the controller.
要跟进,您可以使用custom error classes 或单独的函数来抛出/处理您的错误。
【讨论】:
以上是关于打字稿和多个类的主要内容,如果未能解决你的问题,请参考以下文章