AngularJS迁移至Angular5:如何通过服务端渲染实现可注入值?
嘿,我来帮你解决从AngularJS迁移到Angular5时,复现服务端渲染可注入值的问题!先梳理下原来Angular1.6的常规做法,再对应到Angular5的实现方案。
先回顾Angular1.6的典型实现
从你给出的index.hbs片段来看,原来的逻辑应该是服务端在页面中渲染全局变量,再包装成AngularJS的可注入常量/值。比如你的模板里会加入类似这样的服务端渲染代码:
<script> window.appConfig = { apiUrl: '{{apiUrl}}', userToken: '{{userToken}}' }; </script>
然后在AngularJS中把这个全局变量转为可注入服务:
angular.module('app') .constant('APP_CONFIG', window.appConfig);
之后就能在控制器或服务里直接注入APP_CONFIG使用了。
Angular5的对应实现方案
Angular5用InjectionToken来实现类似的可注入值,步骤如下:
1. 保持服务端渲染全局变量的逻辑
在你的index.html(或对应的模板文件)里,继续让服务端渲染全局配置变量,位置放在Angular根组件之后:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>Collaborative Tool</title> <link href="favicon.ico" rel="shortcut icon" type="image/x-icon"> </head> <body class="aui content"> <!-- Angular5根组件 --> <app-root></app-root> <!-- 服务端渲染的全局配置 --> <script> window.appConfig = { apiUrl: '{{apiUrl}}', userToken: '{{userToken}}' }; </script> </body> </html>
2. 创建配置类型与注入令牌
在Angular项目中新建一个配置文件src/app/app-config.ts,用来定义配置类型和注入令牌:
// 定义配置的类型接口,保证类型安全 export interface AppConfig { apiUrl: string; userToken: string; } // 创建注入令牌,作为依赖注入的标识 import { InjectionToken } from '@angular/core'; export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');
3. 在根模块中提供配置值
打开根模块AppModule,把全局的window.appConfig注册为APP_CONFIG令牌的提供者:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { APP_CONFIG, AppConfig } from './app-config'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule], declarations: [AppComponent], providers: [ { provide: APP_CONFIG, // 用类型断言处理TypeScript的类型检查,或者看下面的优化方案 useValue: (window as any).appConfig } ], bootstrap: [AppComponent] }) export class AppModule { }
4. 在组件/服务中注入使用
现在你可以在任何组件或服务里注入APP_CONFIG来使用配置了,比如在根组件中:
import { Component, Inject } from '@angular/core'; import { APP_CONFIG, AppConfig } from './app-config'; @Component({ selector: 'app-root', template: `<p>当前API地址:{{ config.apiUrl }}</p>` }) export class AppComponent { constructor(@Inject(APP_CONFIG) public config: AppConfig) { console.log('用户Token:', config.userToken); } }
额外优化:TypeScript类型安全增强
如果不想每次都用(window as any),可以在项目的src/typings.d.ts文件中扩展Window接口的类型:
import { AppConfig } from './app/app-config'; interface Window { appConfig: AppConfig; }
这样之后在模块里就能直接写window.appConfig,不需要类型断言了。
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

