所以我有一个名为AuthService的身份验证服务。它处理JWT身份验证并具有属性loggedIn
。此服务已导入我的App Component。
在应用程序组件中,我还包括一个Navbar组件,它显示一些导航。我使用* ngIf来显示登录按钮或注销按钮以及当前登录的用户。其值由AuthService提供。
如果我在Navbar Component中导入AuthService,一切正常。但不是如果它仅包含在App组件中。我认为Angular 2中的导入工作是层次化的,我在父级别导入的内容应该在子级别上可用。或者我错了?
这就是我认为应该如何运作,但事实并非如此:
// app.component.ts
import { Component } from 'angular2/core';
import { ROUTER_DIRECTIVES, RouteConfig } from 'angular2/router';
import { NavbarComponent } from './navbar.component';
import { LoginComponent } from './login.component';
import { HomeComponent } from '../+home/index';
import { Admin } from '../shared/models/admin.model';
import { AuthService } from '../shared/services/auth.service';
@Component({
selector: 'fac-app',
providers: [AuthService, Admin],
templateUrl: 'app/components/app.component.html',
directives: [ROUTER_DIRECTIVES, NavbarComponent, SecretComponent]
})
@RouteConfig([
{
path: '/',
name: 'Home',
component: HomeComponent,
useAsDefault: true
},
{
path: '/login',
name: 'Login',
component: LoginComponent
},
{
path: '/secret',
name: 'Secret',
component: SecretComponent
}
])
export class AppComponent {
constructor(private authService: AuthService) {}
}
// navbar.component.ts
import { Component } from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
@Component({
selector: 'fac-navbar',
templateUrl: 'app/components/navbar.component.html',
styleUrls: ['app/components/navbar.component.css'],
directives: [ROUTER_DIRECTIVES]
})
export class NavbarComponent {
}
// navbar.component.html
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a [routerLink]="['Home']">Home</a></li>
<li><a *ngIf="!authService.loggedIn" [routerLink]="['Login']">Login</a></li>
<li><a *ngIf="authService.loggedIn" href="#">Logout</a></li>
</ul>
<p *ngIf="authService.loggedIn" class="navbar-text navbar-right">Signed in as {{authService.currentUserDisplayName()}}</p>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
// auth.service.ts
import { Http, Headers } from 'angular2/http';
import { Router } from 'angular2/router';
import { Injectable } from 'angular2/core';
import { JwtHelper, AuthHttp, AuthConfig, tokenNotExpired } from 'angular2-jwt';
import { Admin } from '../models/admin.model';
@Injectable()
export class AuthService {
token: any;
jwtHelper: JwtHelper = new JwtHelper();
private loggedIn: boolean = false;
constructor(private http: Http, private router: Router, private authHttp: AuthHttp, private admin: Admin) {
this.loggedIn = tokenNotExpired('auth_token');
}
saveJwt(jwt: any) {
if(jwt) {
localStorage.setItem('auth_token', jwt);
this.token = localStorage.getItem('auth_token');
this.loggedIn = true;
}
}
getJwt() {
if(this.isAuth()) {
return localStorage.getItem('auth_token');
}
}
deleteJwt() {
localStorage.removeItem('auth_token');
this.token = localStorage.getItem('auth_token');
}
isAuth() {
return tokenNotExpired('auth_token');
}
login(admin: Admin) {
var header = new Headers();
header.append('Content-Type', 'application/json');
return this.authHttp.post('http://localhost:4000/api/v1/sessions', JSON.stringify({data: {attributes: { email: admin.email, password: admin.password } }}), {
headers: header
});
}
logout() {
this.deleteJwt();
this.loggedIn = false;
this.router.navigate(['Home']);
}
currentUserDisplayName() {
var jwt: any = this.getJwt();
var decodedToken: any = this.jwtHelper.decodeToken(jwt);
return decodedToken.displayname;
}
}
这是工作版本:
// navbar.component.ts
import { Component } from 'angular2/core';
import {ROUTER_DIRECTIVES} from 'angular2/router';
import { AuthService } from '../shared/services/auth.service';
@Component({
selector: 'fac-navbar',
templateUrl: 'app/components/navbar.component.html',
styleUrls: ['app/components/navbar.component.css'],
directives: [ROUTER_DIRECTIVES]
})
export class NavbarComponent {
constructor(private authService: AuthService) { }
}
答案 0 :(得分:1)
在*ngIf="!authService.loggedIn"
等模板中的表达式在组件实例的范围内进行评估。所以,它实际上是navbarComponentInstance.authService.logged
。当您在构造函数中省略private authService: AuthService
时,navbarComponentInstance.authService
显然是未定义的。
“我在父级别导入的内容应该在子级别上可用。”是的,当且仅当您在子构造函数中声明服务属性时,才可以将服务实例注入子组件。并且,如果已将该服务添加到父组件的providers
,请不要将该服务添加到该组件中。