Javascript 如何将从后端渲染的参数传递到angular2引导方法

Javascript 如何将从后端渲染的参数传递到angular2引导方法,javascript,angular,Javascript,Angular,有没有办法将后端呈现的参数传递给angular2引导方法?我想使用从后端提供的值为所有请求设置http头。我的main.ts文件如下所示: import { bootstrap } from '@angular/platform-browser-dynamic'; import { AppComponent } from "./app.component.ts"; bootstrap(AppComponent); <script> var params = {"token":

有没有办法将后端呈现的参数传递给angular2引导方法?我想使用从后端提供的值为所有请求设置http头。我的
main.ts
文件如下所示:

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";

bootstrap(AppComponent);
<script>
  var params = {"token": "@User.Token", "xxx": "@User.Yyy"};
  System.import('app/main').then((module) => {
    module.main(params);
  });
</script>
我找到了如何将此参数传递给根组件(),但在激发
bootstrap
method时需要它。。。有什么想法吗

编辑:

webpack.config.js内容:

module.exports = {
  entry: {
    app: "./Scripts/app/main.ts"
  },

  output: {
    filename: "./Scripts/build/[name].js"
  },

  resolve: {
    extensions: ["", ".ts", ".js"]
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
};

更新2

更新AoT

为了与AoT合作,工厂关闭需要移出

function loadContext(context: ContextService) {
  return () => context.load();
}

@NgModule({
  ...
  providers: [ ..., ContextService, { provide: APP_INITIALIZER, useFactory: loadContext, deps: [ContextService], multi: true } ],
另见

更新RC.6和2.0.0最终示例

function configServiceFactory (config: ConfigService) {
  return () => config.load();
}

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule,
        routes,
        FormsModule,
        HttpModule],
    providers: [AuthService,
        Title,
        appRoutingProviders,
        ConfigService,
        { provide: APP_INITIALIZER,
          useFactory: configServiceFactory
          deps: [ConfigService], 
          multi: true }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }
如果不需要等待初始化完成,也可以使用`class AppModule{}的构造函数:

class AppModule {
  constructor(/*inject required dependencies */) {...} 
}
提示(循环依赖)

例如,注入路由器可能导致循环依赖。 要解决此问题,请注入
注入器
,然后通过

this.myDep = injector.get(MyDependency);
而不是直接注入
MyDependency
,如:

@Injectable()
export class ConfigService {
  private router:Router;
  constructor(/*private router:Router*/ injector:Injector) {
    setTimeout(() => this.router = injector.get(Router));
  }
}
更新

这在RC.5中应该同样适用,但将提供程序添加到根模块的
提供程序:[……]
,而不是
引导(…)

(我还没有测试过自己)

更新

这里解释了一种完全在角度内完成的有趣方法

您可以使用
APP\u初始值设定项
,当 应用程序已初始化,如果函数返回,则延迟它提供的内容 承诺。这意味着该应用程序可以在不进行任何初始化的情况下进行初始化 您还可以使用现有的服务和框架 特征

例如,假设您有一个多租户解决方案,其中 站点信息依赖于提供服务的域名。这个可以 可以是[name].letterpress.com或在上匹配的自定义域 完整主机名。我们可以通过以下方式隐藏这一事实:这是一项承诺的背后 使用
APP\u初始值设定项

在引导中:

{provide: APP_INITIALIZER, useFactory: (sites:SitesService) => () => sites.load(), deps:[SitesService, HTTP_PROVIDERS], multi: true}),
sites.service.ts:

@Injectable()
export class SitesService {
  public current:Site;

  constructor(private http:Http, private config:Config) { }

  load():Promise<Site> {
    var url:string;
    var pos = location.hostname.lastIndexOf(this.config.rootDomain);
    var url = (pos === -1)
      ? this.config.apiEndpoint + '/sites?host=' + location.hostname
      : this.config.apiEndpoint + '/sites/' + location.hostname.substr(0, pos);
    var promise = this.http.get(url).map(res => res.json()).toPromise();
    promise.then(site => this.current = site);
    return promise;
  }
或者直接提供准备好的
BaseRequestOptions
,就像

class MyRequestOptions extends BaseRequestOptions {
  constructor (private headers) {
    super();
  }
} 

var values = ... // get the headers from the server
var headers = new MyRequestOptions(values);

bootstrap(AppComponent, [{provide: BaseRequestOptions, useValue: headers})]);

唯一的方法是在定义提供者时提供以下值:

bootstrap(AppComponent, [
  provide(RequestOptions, { useFactory: () => {
    return new CustomRequestOptions(/* parameters here */);
  });
]);
然后,您可以在
CustomRequestOptions
类中使用这些参数:

export class AppRequestOptions extends BaseRequestOptions {
  constructor(parameters) {
    this.parameters = parameters;
  }
}
如果从AJAX请求中获取这些参数,则需要通过以下方式异步引导:

var appProviders = [ HTTP_PROVIDERS ]

var app = platform(BROWSER_PROVIDERS)
  .application([BROWSER_APP_PROVIDERS, appProviders]);

var http = app.injector.get(Http);
http.get('http://.../some path').flatMap((parameters) => {
  return app.bootstrap(appComponentType, [
    provide(RequestOptions, { useFactory: () => {
      return new CustomRequestOptions(/* parameters here */);
    }})
  ]);
}).toPromise();
见这个问题:

编辑

由于您的数据是HTML格式的,因此可以使用以下内容

您可以导入函数并使用参数调用它

以下是引导应用程序的主模块示例:

import {bootstrap} from '...';
import {provide} from '...';
import {AppComponent} from '...';

export function main(params) {
  bootstrap(AppComponent, [
    provide(RequestOptions, { useFactory: () => {
      return new CustomRequestOptions(params);
    });
  ]);
}
然后,您可以从HTML主页导入它,如下所示:

import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from "./app.component.ts";

bootstrap(AppComponent);
<script>
  var params = {"token": "@User.Token", "xxx": "@User.Yyy"};
  System.import('app/main').then((module) => {
    module.main(params);
  });
</script>

var params={“token”:“@User.token”,“xxx”:“@User.Yyy”};
System.import('app/main')。然后((模块)=>{
主模块(参数);
});

请参阅此问题:.

在Angular2最终版本中,可以使用APP\u初始值设定项提供程序实现您想要的功能

我用一个完整的例子写了一个要点:

gist示例是从JSON文件读取,但是可以很容易地更改为从REST端点读取

您需要的基本上是:

a) 在现有模块文件中设置APP_初始值设定项:

import { APP_INITIALIZER } from '@angular/core';
import { BackendRequestClass } from './backend.request';
import { HttpModule } from '@angular/http';

...

@NgModule({
    imports: [
        ...
        HttpModule
    ],
    ...
    providers: [
        ...
        ...
        BackendRequestClass,
        { provide: APP_INITIALIZER, useFactory: (config: BackendRequestClass) => () => config.load(), deps: [BackendRequestClass], multi: true }
    ],
    ...
});
在应用程序启动之前,这些行将从BackendRequestClass类调用load()方法

如果要使用angular2内置库对后端进行http调用,请确保在“导入”部分设置“HttpModule”

b) 创建一个类并将文件命名为“backend.request.ts”:

c) 要读取后端调用的内容,只需将BackendRequestClass注入到您选择的任何类中并调用getResult()。例如:

import { BackendRequestClass } from './backend.request';

export class AnyClass {
    constructor(private backendRequest: BackendRequestClass) {
        // note that BackendRequestClass is injected into a private property of AnyClass
    }

    anyMethod() {
        this.backendRequest.getResult(); // This should return the data you want
    }
}

让我知道这是否解决了您的问题。

您可以创建并导出一个函数来完成以下工作,而不是让入口点本身调用引导:

export function doBootstrap(data: any) {
    platformBrowserDynamic([{provide: Params, useValue: new Params(data)}])
        .bootstrapModule(AppModule)
        .catch(err => console.error(err));
}
您还可以将此函数放置在全局对象上,具体取决于您的设置(webpack/SystemJS)。它也是AOT兼容的


这有额外的好处来延迟引导,当它有意义的时候。例如,当您在用户填写表单后以AJAX调用的形式检索此用户数据时。只需使用这些数据调用导出的引导函数。

但如何将这些参数呈现到typescript文件中?或者我应该在第页的内联脚本中运行这个引导方法吗?但是,当使用es6导入时,如何做到这一点?渲染的确切含义是什么?您是否从服务器生成主HTML文件/JS文件?您是否执行AJAX请求来获取这些参数?我从服务器生成视图。我想我将在后端呈现所有必要的参数,如下所示:
{“token”:“@User.token”,“xxx”:“@User.Yyy”}
因此在呈现的HTML中我将有
{“token”:“123abc456def”,“xxx”:“Yyy”}
。我想以某种方式将这个呈现的JSON传递到引导方法中,我在.js文件中有这个方法。有没有办法不用SystemJS运行这个方法(我使用的是webpack,入口点在webpack.config文件中定义)我不是webpack专家,但我可以试试。。。能否添加webpack.config文件的内容?谢谢因此,您希望从HTML中读取。您可以在服务器上添加一个脚本标记,将它们分配给某个全局变量
function(){window.headers=someJson;}()
。不确定语法,我自己也不太使用JS。这样你就不必解析了。很好的解决方案,只需给像我这样的未来谷歌用户几句话:1)注意
load()
必须返回
承诺,而不是
可观察的
。如果您像我一样在服务中使用可观察对象,请使用
.toPromise()
函数。2) 您可能想知道如何将值
sites.load()
检索到您的服务、组件等中
export function doBootstrap(data: any) {
    platformBrowserDynamic([{provide: Params, useValue: new Params(data)}])
        .bootstrapModule(AppModule)
        .catch(err => console.error(err));
}