如何在Aurelia中最好地使用全局服务类

如何在Aurelia中最好地使用全局服务类,aurelia,Aurelia,我的应用程序中有许多类使用的一些服务。例如,LoggerService将消息记录到内部存储并打印到控制台 此服务可能看起来像这样: export class LoggerService { let _logs = []; addLog(msg) { this._logs.push(msg); console.log(this._logs.length + ': ' + msg); } } import {autoinject, Aure

我的应用程序中有许多类使用的一些服务。例如,
LoggerService
将消息记录到内部存储并打印到控制台

此服务可能看起来像这样:

export class LoggerService {
    let _logs = [];

    addLog(msg) {
        this._logs.push(msg);
        console.log(this._logs.length + ': ' + msg);
    }
}
import {autoinject, Aurelia} from 'aurelia-framework';
import {LoggerService} from 'LoggerService';

@autoinject
export class SomeViewModel {
    let _loggerService;

    constructor(loggerService) {
        this._loggerService = loggerService
    }

    somethingChanged() {
        this._loggerService.addLog('Something changed...');
    }
}
我猜在Aurelia中通常的方法是将这个类与依赖项注入一起使用,这很好,因为它在每个默认值中使用一个单例。示例用法如下所示:

export class LoggerService {
    let _logs = [];

    addLog(msg) {
        this._logs.push(msg);
        console.log(this._logs.length + ': ' + msg);
    }
}
import {autoinject, Aurelia} from 'aurelia-framework';
import {LoggerService} from 'LoggerService';

@autoinject
export class SomeViewModel {
    let _loggerService;

    constructor(loggerService) {
        this._loggerService = loggerService
    }

    somethingChanged() {
        this._loggerService.addLog('Something changed...');
    }
}
基本上,这种方法效果很好,但在更大范围内感觉有点“笨拙”,我希望可以简化:

  • 使用依赖项注入需要在每个“使用类”中使用大量样板代码,这会不必要地“膨胀”它们(导入语句、需要在构造函数中分配的专用类成员等)
  • 我习惯于在一个位于窗口对象中的专用名称空间中包含这样的类。这使我能够方便地进行调试,因为我可以调用类似于
    MyNamespace.LoggerService.addLog('blahblah')的代码。我怎样才能用Aurelia做到最好

有没有更直接的方法可以让我从命令行获得更好的调试体验?

诚实的回答?如果您遵循ES6模块化代码约定,则不一定。如果需要,您将始终导入模块。你可以做一些事情,我会在这个答案中解释

如果你不想,你实际上不需要使用Aurelia的依赖注入。但是,这意味着您必须自己处理对象的生命周期。因为您的对象是一个类,所以在导入时必须对其调用“new”。但是,您可以以不同的方式编写日志模块,并且可以导出函数,而不是导出类,如下所示:

let _logs = [];

export var LoggerService = {
    addLog: function (msg) {
        _logs.push(msg);
        console.log(_logs.length + ': ' + msg);
    }
}
这样,您只需导入LoggerService并在Aurelia视图中调用
LoggerService.addLog
,而无需注入它。这是一种比类实例化方法更具功能性的方法,它可以很好地工作

import {LoggerService} from 'LoggerService';

export class SomeViewModel {    
    constructor() {
    }

    somethingChanged() {
        LoggerService.addLog('Something changed...');
    }
}
您可以做的另一件事(我不建议这样做)是简单地将其作为一个窗口变量。这意味着您不必导入模块。不过,这违反了模块原则,事情很快就会变得一团糟。模块的存在是有原因的,尽管import语句确实添加了几行代码,但额外的空间还是值得的

对于您的用例,我将使用上面基于函数的方法,并在某处检查“development”标志,以便您可以公开窗口对象上的属性,以便您可以通过控制台访问它们。(您不希望在生产环境中使用此功能,因为人们可能很容易弄乱您的应用程序)

if (developmentFlag) { window.loggerService = LoggerService; }

这可能是最好的方法,直到我们能够在控制台REPL中运行
import
语句。

从控制台调试和使用单例服务不是正交的。正如答案所说,只需使用
window.loggerService=loggerService
(它不限于记录器,而是任何有助于调试的对象)即可解决。DI提供了一定程度的灵活性,您永远不知道何时需要它。不必要的“臃肿”他们的论点适用于大多数被认为是良好实践的事情。非常感谢您提供了这个详尽的答案和良好的示例!