javascript - Angular 2 : Why do I have to import a Service in a child component if it is already included in the app component?

标签 javascript angular

所以我有一个名为 AuthService 的身份验证服务。它处理 JWT 身份验证并具有属性 loggedIn。该服务已导入我的应用程序组件中。

在应用程序组件中,我还包含一个导航栏组件,用于显示一些导航。我使用 *ngIf 显示登录按钮或注销按钮以及当前登录的用户。该值由 AuthService 提供。

如果我在导航栏组件中导入 AuthService,一切都会正常。但如果它仅包含在应用程序组件中则不然。我认为 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) {  }

}

最佳答案

  1. *ngIf="!authService.loggedIn" 等模板中的表达式在组件实例的范围内进行计算。所以,它实际上是 navbarComponentInstance.authService.logged。当您在构造函数中省略 private authService: AuthService 时,navbarComponentInstance.authService 显然是未定义的。

  2. “我在父级别导入的内容应该在子级别可用。”是的,当且仅当您在子构造函数中声明服务属性时,服务实例才可以注入(inject)到子组件中。并且,如果该服务已添加到父组件的 providers 中,请勿将其添加到子组件的 providers 中。

关于javascript - Angular 2 : Why do I have to import a Service in a child component if it is already included in the app component?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37457259/

相关文章:

javascript - 使用 react-router v4 和 express.js 渲染服务器

javascript - 如何使用Moment js将UTC时间转换为正常时间格式

带有 Typescript 的 Angular2 - 加载 angular2/平台/浏览器时出错

angular - 动态更改标签? Angular 2

javascript - Angular 帖子未按预期提供请求正文

JavaScript 多维数组 - 列到行

javascript - 为什么单选按钮中需要不规则的消息(jquery 验证)?

javascript - 通过 forkJoin 和响应识别的并行 http 请求

angular - 有没有一种简单的方法可以取消选择 Ionic 2 中的 ionic radio ?

angular - 在 Angular 中的 SPA 应用程序上的 Microsoft Azure AD 身份验证中,根据客户端信用获取访问 token 时出现 CORS 错误