Angular 2.1.2/2.2.0 依赖注入实例未定义
Angular 2.1.2/2.2.0 dependency injection instance undefined
在将我的代码从 RC4 迁移到 2.1.2 的过程中,我遇到了一个奇怪的问题:我所有的构造函数参数都未定义它们的值。
我试图将提供程序从组件移动到 app.module.ts 再到 app.component.ts。 None 其中有效。
2.1.2 中的新功能可以使依赖项注入器注入 "undefined" 而不是 creating/providing 服务实例?
备注
- 为了使事情更简单,我将代码更改为以下内容
- 没有错误信息。
- 如果我不将 @Injectable() 添加到 AppComponent 我会得到
Can't resovle all parameters for AppComponent (?,?,?)
- 请注意,根注入器未能同时创建用户服务和路由器实例来提供 AppComponent 构造函数。
- AuthService 曾经用于注入 Http,但我将其与其他代码一起删除,这样拼图的变数就更少了。
- 在Angular 2.2.0 中试过,也不行。
还有什么意见吗?
app.component.ts
import { Component,Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../login/auth.service';
@Component({
selector: 'my-app',
template: `
<h1 class="title">Angular Router</h1>
<nav>
</nav>
<router-outlet></router-outlet>
`
})
@Injectable()
export class AppComponent {
constructor( // debug here
private auth: AuthService, // auth = undefined
private router: Router, // router = undefined
) {
console.log("AppComponent constructor");
}
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { AuthService } from '../login/auth.service';
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{ path: '', component: AppComponent },
])
],
declarations: [ AppComponent ],
exports: [RouterModule],
providers:[AuthService ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
auth.service.ts
import {Injectable} from '@angular/core';
@Injectable()
export class AuthService { // the debugger can get to this line but never hit constructor
private _baseUrl: string;
loggedIn: boolean = false;
redirectUrl: string;
constructor() {
console.log("AuthService constuctor");
this.loggedIn = !!sessionStorage.getItem('auth_token');
}
}
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './appShell/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
systemjs.config.js
(function(global) {
var ngVer = '@2.1.2'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.1.2'; // lock router version
//map tells the System loader where to look for things
var map = {
'app': 'app',
// angular bundles
'@angular/core': 'https://npmcdn.com/@angular/core' + ngVer,
'@angular/common': 'https://npmcdn.com/@angular/common' + ngVer,
'@angular/compiler': 'https://npmcdn.com/@angular/compiler' + ngVer,
'@angular/platform-browser': 'https://npmcdn.com/@angular/platform-browser' + ngVer,
'@angular/platform-browser-dynamic': 'https://npmcdn.com/@angular/platform-browser-dynamic' + ngVer,
'@angular/http': 'https://npmcdn.com/@angular/http' + ngVer,
'@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
'@angular/forms': 'https://npmcdn.com/@angular/forms' + ngVer,
'@angular/upgrade': 'https://npmcdn.com/@angular/upgrade' + ngVer,
// Other libraries
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.12',
'angular-in-memory-web-api': 'https://npmcdn.com/angular-in-memory-web-api', // get latest
'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
'typescript': 'https://npmcdn.com/typescript@2.0.3/lib/typescript.js',
};
//packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.ts', defaultExtension: 'ts' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
};
var config = {
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
meta: {
'typescript': {
"exports": "ts"
}
},
map: map,
packages: packages
};
System.config(config);
})(this);
package.json
{
"name": "TestApp",
"version": "1.0.0",
"scripts": {
"start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
"lite": "lite-server",
"tsc": "tsc",
"tsc:w": "tsc -w"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@angular/common": "~2.1.2",
"@angular/compiler": "~2.1.2",
"@angular/core": "~2.1.2",
"@angular/forms": "~2.1.2",
"@angular/http": "~2.1.2",
"@angular/platform-browser": "~2.1.2",
"@angular/platform-browser-dynamic": "~2.1.2",
"@angular/router": "~3.1.2",
"@angular/upgrade": "~2.1.2",
"angular-in-memory-web-api": "~0.1.13",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.40",
"zone.js": "^0.6.26"
},
"devDependencies": {
"@types/core-js": "^0.9.34",
"@types/node": "^6.0.46",
"concurrently": "^3.1.0",
"lite-server": "^2.2.2",
"typescript": "^2.0.3"
},
"repository": {}
}
在 RC.5 中 @NgModule was introduced。
您需要像这样声明额外的服务、模块等:
import {NgModule} from '@angular/core';
import {LoginComponent} from './login.component';
import {Router,RouterModule} from '@angular/router';
import {FormsModule, FormBuilder} from '@angular/forms';
import {AuthService} from './auth.service';
import {routing} from './app.routing.module';
import {MainComponent} from './main.component';
@NgModule({
declarations: [LoginComponent], // specify your components here
imports: [BrowserModule, FormsModule, RouterModule.forRoot([...]), routing],
providers: [FormBuilder, AuthService, ...], // additional providers
bootstrap: [MainComponent],
})
class AppModule {}
终于找到了。在 systemjs.config.js 中添加以下内容,效果很好。
typescriptOptions: {
emitDecoratorMetadata: true
},
我有一点建议。尽量不要在组件上使用 @Injector 装饰器,而是定义一个服务并在那里使用它。它使您的代码更具可读性。
在将我的代码从 RC4 迁移到 2.1.2 的过程中,我遇到了一个奇怪的问题:我所有的构造函数参数都未定义它们的值。
我试图将提供程序从组件移动到 app.module.ts 再到 app.component.ts。 None 其中有效。
2.1.2 中的新功能可以使依赖项注入器注入 "undefined" 而不是 creating/providing 服务实例?
备注
- 为了使事情更简单,我将代码更改为以下内容
- 没有错误信息。
- 如果我不将 @Injectable() 添加到 AppComponent 我会得到
Can't resovle all parameters for AppComponent (?,?,?)
- 请注意,根注入器未能同时创建用户服务和路由器实例来提供 AppComponent 构造函数。
- AuthService 曾经用于注入 Http,但我将其与其他代码一起删除,这样拼图的变数就更少了。
- 在Angular 2.2.0 中试过,也不行。
还有什么意见吗?
app.component.ts
import { Component,Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { AuthService } from '../login/auth.service';
@Component({
selector: 'my-app',
template: `
<h1 class="title">Angular Router</h1>
<nav>
</nav>
<router-outlet></router-outlet>
`
})
@Injectable()
export class AppComponent {
constructor( // debug here
private auth: AuthService, // auth = undefined
private router: Router, // router = undefined
) {
console.log("AppComponent constructor");
}
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component';
import { AuthService } from '../login/auth.service';
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot([
{ path: '', component: AppComponent },
])
],
declarations: [ AppComponent ],
exports: [RouterModule],
providers:[AuthService ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
auth.service.ts
import {Injectable} from '@angular/core';
@Injectable()
export class AuthService { // the debugger can get to this line but never hit constructor
private _baseUrl: string;
loggedIn: boolean = false;
redirectUrl: string;
constructor() {
console.log("AuthService constuctor");
this.loggedIn = !!sessionStorage.getItem('auth_token');
}
}
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './appShell/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
systemjs.config.js
(function(global) {
var ngVer = '@2.1.2'; // lock in the angular package version; do not let it float to current!
var routerVer = '@3.1.2'; // lock router version
//map tells the System loader where to look for things
var map = {
'app': 'app',
// angular bundles
'@angular/core': 'https://npmcdn.com/@angular/core' + ngVer,
'@angular/common': 'https://npmcdn.com/@angular/common' + ngVer,
'@angular/compiler': 'https://npmcdn.com/@angular/compiler' + ngVer,
'@angular/platform-browser': 'https://npmcdn.com/@angular/platform-browser' + ngVer,
'@angular/platform-browser-dynamic': 'https://npmcdn.com/@angular/platform-browser-dynamic' + ngVer,
'@angular/http': 'https://npmcdn.com/@angular/http' + ngVer,
'@angular/router': 'https://npmcdn.com/@angular/router' + routerVer,
'@angular/forms': 'https://npmcdn.com/@angular/forms' + ngVer,
'@angular/upgrade': 'https://npmcdn.com/@angular/upgrade' + ngVer,
// Other libraries
'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.12',
'angular-in-memory-web-api': 'https://npmcdn.com/angular-in-memory-web-api', // get latest
'ts': 'https://npmcdn.com/plugin-typescript@4.0.10/lib/plugin.js',
'typescript': 'https://npmcdn.com/typescript@2.0.3/lib/typescript.js',
};
//packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': { main: 'main.ts', defaultExtension: 'ts' },
'rxjs': { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
};
var config = {
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
meta: {
'typescript': {
"exports": "ts"
}
},
map: map,
packages: packages
};
System.config(config);
})(this);
package.json
{
"name": "TestApp",
"version": "1.0.0",
"scripts": {
"start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
"lite": "lite-server",
"tsc": "tsc",
"tsc:w": "tsc -w"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@angular/common": "~2.1.2",
"@angular/compiler": "~2.1.2",
"@angular/core": "~2.1.2",
"@angular/forms": "~2.1.2",
"@angular/http": "~2.1.2",
"@angular/platform-browser": "~2.1.2",
"@angular/platform-browser-dynamic": "~2.1.2",
"@angular/router": "~3.1.2",
"@angular/upgrade": "~2.1.2",
"angular-in-memory-web-api": "~0.1.13",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.40",
"zone.js": "^0.6.26"
},
"devDependencies": {
"@types/core-js": "^0.9.34",
"@types/node": "^6.0.46",
"concurrently": "^3.1.0",
"lite-server": "^2.2.2",
"typescript": "^2.0.3"
},
"repository": {}
}
在 RC.5 中 @NgModule was introduced。
您需要像这样声明额外的服务、模块等:
import {NgModule} from '@angular/core';
import {LoginComponent} from './login.component';
import {Router,RouterModule} from '@angular/router';
import {FormsModule, FormBuilder} from '@angular/forms';
import {AuthService} from './auth.service';
import {routing} from './app.routing.module';
import {MainComponent} from './main.component';
@NgModule({
declarations: [LoginComponent], // specify your components here
imports: [BrowserModule, FormsModule, RouterModule.forRoot([...]), routing],
providers: [FormBuilder, AuthService, ...], // additional providers
bootstrap: [MainComponent],
})
class AppModule {}
终于找到了。在 systemjs.config.js 中添加以下内容,效果很好。
typescriptOptions: {
emitDecoratorMetadata: true
},
我有一点建议。尽量不要在组件上使用 @Injector 装饰器,而是定义一个服务并在那里使用它。它使您的代码更具可读性。