11

我正在开发一个 ionic2 项目,我需要创建一个新的自定义 JSON 配置文件。我找到了一些教程来创建一个并通过 http.get 访问它,但我认为通过 get 请求调用它很奇怪。我希望它在根文件夹中(所有配置 JSON 都在其中),我直接打开/读取文件。

我不知道这是否可能,甚至推荐?这就是为什么我在这里发布一些意见和解决方案:)

谢谢

4

2 回答 2

14

就我个人而言,我不喜欢通过使用 http.get方式来处理配置信息来读取 config.json 文件,即使必须有另一种方法来在代码中包含和读取json 文件,因为我们正在使用Angular2 和 Typescript,为什么不使用类、接口并以更花哨的方式来做呢?

接下来我将向您展示的内容可能看起来比最初应该更复杂(尽管阅读后您会发现它非常简单易懂),但是当我开始学习 Angular2 时,我看到了他们如何处理配置文件的示例依赖注入指南,我在我处理配置信息(如 API 端点、默认值等)的应用程序中遵循了该指南。

根据文档:

非类依赖

[...]

应用程序通常定义带有许多小事实的配置对象(例如应用程序的标题或 Web API 端点的地址),但这些配置对象并不总是类的实例。

为非类依赖项选择提供者令牌的一种解决方案是定义和使用 OpaqueToken

因此,您需要使用 url 等定义一个配置对象,然后在OpaqueToken使用您的配置注入对象时能够使用它。

我在app-config.ts文件中包含了我的所有配置

// Although the ApplicationConfig interface plays no role in dependency injection, 
// it supports typing of the configuration object within the class.
export interface ApplicationConfig {
  appName: string;
  apiEndpoint: string;
}

// Configuration values for our app
export const MY_CONFIG: ApplicationConfig = {
  appName: 'My new App',
  apiEndpoint: 'http://www...'
};

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new OpaqueToken('config');

OpaqueToken起初可能令人困惑,但它只是一个字符串,可以在注入此对象时避免命名冲突。你可以在这里找到一篇关于这个的精彩帖子。

然后,您只需要将它包含在您需要它的页面中,如下所示:

import { NavController } from 'ionic-angular/index';
import { Component, OpaqueToken, Injectable, Inject } from "@angular/core";

// Import the config-related things
import { MY_CONFIG_TOKEN, MY_CONFIG, ApplicationConfig } from 'app-config.ts';

@Component({
  templateUrl:"home.html",
  providers: [{ provide: MY_CONFIG_TOKEN, useValue: MY_CONFIG }]
})
export class HomePage {

  private appName: string;
  private endPoint: string;

  constructor(@Inject(MY_CONFIG_TOKEN) private config: ApplicationConfig) {
    this.appName = config.appName;
    this.endPoint = config.apiEndpoint;
  }
}

请注意如何将其包含在providers数组中

providers: [{ provide: MY_CONFIG_TOKEN, useValue: MY_CONFIG }]

以及如何告诉注入器它应该如何获取配置对象的实例

@Inject(MY_CONFIG_TOKEN) config: ApplicationConfig

更新

OpaqueToken自 v4.0.0 起已弃用,因为它不支持类型信息,请InjectionToken<?>改用。

所以代替这些行:

import { OpaqueToken } from '@angular/core';

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new OpaqueToken('config');

现在我们应该使用

import { InjectionToken } from '@angular/core';

// Create a config token to avoid naming conflicts
export const MY_CONFIG_TOKEN = new InjectionToken<ApplicationConfig>('config');
于 2016-09-19T16:28:33.627 回答
3

在阅读和阅读不同的解决方案后,我最终使用了这个 hacky 实现。希望很快就会有一个不错的原生解决方案:

import { NgModule } from '@angular/core';
import { environment as devVariables } from './environment.dev';
import { environment as testVariables } from './environment.test';
import { environment as prodVariables } from './environment.prod';

export function environmentFactory() {
  const location = window.location.host;
  switch (location) {
    case 'www.example.org': {
      return prodVariables;
    }
    case 'test.example.org': {
      return testVariables;
    }
    default: {
      return devVariables;
    }
  }
}

@NgModule({
  providers: [
    {
      provide: 'configuration',
      useFactory: environmentFactory
    }
  ]
})
export class EnvironmentsModule {}

然后在需要的地方,例如:

import { Injectable, Injector, Inject } from '@angular/core';

import { AuthenticationService } from '../authentication';

@Injectable()
export class APIService {

  private http: Http;
  private apiURL: string;
  protected authentication: AuthenticationService;

  constructor(
    public injector: Injector,
    @Inject('configuration') public configuration: any
  ) {
    this.http = injector.get(Http);
    this.authentication = injector.get(AuthenticationService);
    this.apiURL = configuration.apiURL;    
  };

...
于 2017-05-08T12:50:13.327 回答