文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

最终2.0版本的发布标志着Angular 2正式到达一个里程碑式的阶段 ,在过去短短几个星期之内已经发布了5个候选版本,引入了众多新的特性,这使得开发者更加容易开发运行得更快更稳定的Angular 2应用。有以下新特性:路由支持延迟加载,组件和服务提前编译,一个全新改进的表单模块和一个叫做@NgModule的装饰器。

在你的Angular 2应用中,NgModule 旨在简化定义和管理依赖的方式,使用 @NgModule 你能够 把不同的组件和服务聚合成功能模块

第 1 段(可获 1.33 积分)

"在你的Angular 2应用中使用@NgModule帮助你简化定义和管理依赖的方式"

没有@NgModule的Angular 2

NgModule是Angular 2框架中来得有点晚但是很受欢迎的新特性,在深入研究使用@NgModule之前,让我们先简要地看看没有它的情况是怎样的。如果使用RC5以下版本的Angular 2应用,你的组件很可能是这样的:

@Component({
  selector: 'my-component',
  styles: [`
  h1 {
    font-size: 200px
  }
  `]
  template: `
  <h1>Hello from MyComponent.</h1>
  <my-other-component></my-other-component>
  `,
  providers: [MyProvider], // MyProvider is a fictional service
  directives: [MyOtherComponent] // MyOtherDirective is a fictional component
})
export class MyComponent {}
第 2 段(可获 0.78 积分)

对每一个你创建的组件,在你的应用中必须声明这些不同组件,服务和管道之间的关系。很容易就会忘记地把组件正确地包含进来,这会使得管理依赖变得很麻烦。除此之外,错误日志报告信息很有限,你甚至不知道为什么你的应用运行失败或者一些方法为什么就失败了。

了解@NgModule

@NgModule是Angular 2应用负责管理依赖的最重要的一部分,通过@NgModule你可以把一些特定的功能,业务逻辑,程序或者其他的逻辑方法封装成一个模块集合,在这个模块(module)中包含所有的组件,服务,管道和指令,不需要在其他地方重复声明这些依赖。

第 3 段(可获 1.81 积分)

让我们来看看它是怎样实际工作的。我们首先引入我们的根模块,RC5和将来的Angular 2版本的程序将不再会被一个组件导入,而是而是使用模块进行导入,因此我们的应用必须有一个根模块。我们像下面这样创建一个根模块:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
第 4 段(可获 0.6 积分)

我们的app.component.ts文件一开始就像下面这么简单:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  template: '<h1>NgModule Demo Application</h1>',
})
export class AppComponent {}

到现在为止,我们声明Angular 应用的语法跟2 RC5以前版本看起来并没有太大区别,当然语法还是稍微变化了,但如果只是这样真的值得重写我们的代码吗?

接下来,让我们给我们的应用增加一个组件,把它命名为WelcomeComponent,这个组件简单地显示一条欢迎消息。实现如下面所示:

第 5 段(可获 0.86 积分)
import { Component } from '@angular/core';

@Component({
  selector: 'app-welcome',
  template: '<p>Welcome to our awesome app</p>',
})
export class WelcomeComponent {}

现在,我们想在AppComponent中使用这个组件,在RC5以前的版本中,我们要这样做:

  1. 进入我们的app.component.ts文件,导入WelComeComponet
  2. 在@Component 装饰器中添加一个指令关键字,然后把 WelcomeComponent传递给给它。
  3. 最后,在模版中添加 <app-welcome></app-welcome>指令

如果我们想在其他任何地方使用WelcomeComponent,就必须重复上面的过程。在一个小型的应用中,这可能只是一个很小的困扰,但是如果你的应用规模增长,这样的操作变得重复枯燥,并且应用会难以管理。

第 6 段(可获 1.01 积分)

由于我们要写一个利用 @NgModule的应用程序,我们可以省略步骤1和步骤2,只是简单的在模版中添加合适的组件。然后,在根@NgModule里面,我们已经简单的把WelcomeComponent作为依赖添加进去了。

// ...
@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent, WelcomeComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
// ...

因为已经在根模块中声明了组件,我们现在不需要再次声明或者重复导入,就可以在应用程序的任意地方使用这个 WelcomeComponent组件。本质上, @NgModule为我们处理依赖注入,因此任何我们声明的组件都会有其他依赖固有的知识图谱。我们不仅仅局限于声明组件,也可以额外声明指令,服务和那些重复使用的逻辑模块。

第 7 段(可获 1.39 积分)

让我们谈谈关于 imports 关键字。 这个imports 关键字在 @NgModule的上下文中定义的用于将别的模块导入到当前模块中。 例如,我们导入 BrowserModule模块,其中添加了很多常用功能,如ngif和ngfor。 通过导入BrowserModule, 我们可以访问所有这些指令,而不必手动声明它们自己。 这就省掉了许多需要重新定义和重复导入的通用功能。

这是一个简单的例子,显示了我们如何利用 @NgModule 装饰器来简化我们的Angular2应用中的依赖管理。 这是一个很简单的解释。 看看官方的 文档去学习 @NgModule的所有内容。 在下一节中, 我们来看看如何利用新的@NgModule特性并将身份验证添加到我们的Angular2应用中。

第 8 段(可获 1.76 积分)

Angular2 身份验证

在过去我们展示了如何通过添加JSON Web令牌(JWT)来给你的Angular2应用进行身份验证。 许多文章都是在pre-RC5版本之前写的,所以今天我们来讨论,如何结合 Angular 2 JWT 库和 @NgModule 类编写更加容易理解,更加高效的代码。

你可能已经熟悉Angular2官方的演示应用英雄指南.。我们fork 它并创建一个分支秘密的英雄之旅s。除了来让你熟悉Angular2是如何工作的, 我们的版本还支持JSON Web基于令牌的身份验证。 L看看我们是如何做到这一点的。

第 9 段(可获 1.39 积分)

首先, 我们使用Angular 2由Auth0创建的JWT 库,. 在你的应用中安装它只需要运行 npm install angular2-jwt --save。

接下来,我们创建了一个身份验证服务在一个auth.service.ts的文件中。 该实现如下:

import { Injectable } from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { Router } from '@angular/router';

declare var Auth0Lock: any;

@Injectable()
export class AuthService {
  // Get the AUTH0_CLIENT_ID and AUTH0_DOMAIN from your management dashboard.
  lock = new Auth0Lock('AUTH0_CLIENT_ID', 'AUTH0_DOMAIN');

  constructor(private router: Router) {
    this.lock.on('authenticated', (authResult: any) => {
      localStorage.setItem('id_token', authResult.idToken);

      this.lock.getProfile(authResult.idToken, (error: any, profile: any) => {
        if (error) {
          console.log(error);
        }

        localStorage.setItem('profile', JSON.stringify(profile));
      });

      this.lock.hide();
    });
  }

  login() {
    this.lock.show();
  }

  logout() {
    // To log out, just remove the token and profile
    // from local storage
    localStorage.removeItem('profile');
    localStorage.removeItem('id_token');

    // Send the user back to the dashboard after logout
    this.router.navigateByUrl('/dashboard');
  }

  loggedIn() {
    return tokenNotExpired();
  }
}
第 10 段(可获 0.45 积分)

实现使用了Auth0 Lock组件。 Lock组件是一个现代的、易于使用,可配置登录窗口小部件可以处理几乎任何身份验证用例。 添加Lock组件到你的应用中,在你的 index.html页面中添加以下代码:


  <!-- Auth0Lock script -->
  <script src="//cdn.auth0.com/js/lock/10.2.2/lock.min.js"></script>

下一步,我们实现了一个认证保护,确定该路由是否加载。实现如下:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { CanActivate } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private auth: AuthService, private router: Router) {}

  canActivate() {
    if (!this.auth.loggedIn()) {
      this.router.navigate(['']);
      return false;
    }
    return true;
  }

}
第 11 段(可获 0.79 积分)

这个AuthGuard检查用户是否已经登录。使用AuthGuard对路由进行保护, 用户必须登录, 否则路由不会加载,并重定向到首页。 在英雄指南的路由配置中,我们在两个路由对象中添加了AuthGuard。

// ...
const appRoutes: Routes = [
  const appRoutes: Routes = [
  {
    path: '',
    redirectTo: '/dashboard',
    pathMatch: 'full'
  },
  {
    path: 'dashboard',
    component: DashboardComponent
  },
  {
    path: 'detail/:id',
    component: HeroDetailComponent
  },
  {
    path: 'heroes',
    component: HeroesComponent
  },
  {
    path: 'secret-heroes',
    component: SecretHeroesComponent,
    canActivate: [AuthGuard]
  },
  {
    path: 'secret-detail/:id',
    component: SecretHeroDetailComponent,
    canActivate: [AuthGuard]
  },
];
];
// ...
第 12 段(可获 0.64 积分)

那些额外添加AuthGuard属性的意味着在这些路由上面会激活对于用户是否登录的验证。 对于这个应用, 我们只创建了一个 Ng模块,就是这个根模块。让我们来看下它的实现。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AUTH_PROVIDERS } from 'angular2-jwt';

import './rxjs-extensions';
import { AppComponent } from './app.component';
import { routing, routedComponents } from './app.routing';
import { HeroService } from './hero.service';
import { HeroSearchComponent } from './hero-search.component';

import { AuthService } from './auth.service';
import { AuthGuard } from './auth-guard.service';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    routing,
    HttpModule
  ],
  declarations: [
    AppComponent,
    HeroSearchComponent,
    routedComponents
  ],
  providers: [
    HeroService,
    AUTH_PROVIDERS,
    AuthService,
    AuthGuard
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
第 13 段(可获 0.51 积分)

正如你看到的, 我们增加了几个不同的 importsdeclarations,和 providers.。因为这是我们的根模块, 我们还增加了一个 bootstrap 关键字,通过它让应用第一个加载该组件。 一个值得注意的是,我们没有包括我们所有的组件在这里.。 DashboardComponent和HeroDetailComponent以及其他的组件都不在这里。这是否意味着我们的应用程序将不工作吗? 不完全是这样。 注意 我们添加到 declarations中的routedComponents 属性。 如果你查看 app.routing.ts这个文件, 你就会注意到我们在路由的配置数组中将所有的组件都分组了, 然后导出它们。 这完全有效而且能正常工作, a会同时使我们的代码容易阅读和理解。

第 14 段(可获 1.5 积分)

我们所做的最后一次改变是在app.component.ts 文件中。 在这个文件中我们更新了模板,并且添加了一个AuthService的私有属性。 这样我们就能够根据用户状态显示菜单选项。 看看下面的实现:

import { Component } from '@angular/core';
import { AuthService } from './auth.service';

@Component({
  moduleId: module.id,
  selector: 'my-app',
  template: `
    <h1></h1>
    <nav>
      <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
      <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
      <a routerLink="/secret-heroes" *ngIf="authService.loggedIn()" routerLinkActive="active">Secret Heroes</a>
      <a (click)=authService.login() *ngIf="!authService.loggedIn()">Log In</a>
      <a (click)=authService.logout() *ngIf="authService.loggedIn()">Log Out</a>
    </nav>
    <router-outlet></router-outlet>
  `,
  styleUrls: ['app.component.css']
})
export class AppComponent {

  title = 'Tour of Heroes';

  constructor(private authService: AuthService) {}
}

就是这样。 我们创建了secret-heroes.component.ts 和secret-hero-details.component.ts 组件, 但是他们的功能相当于普通的 heroes.component.ts 和hero-details.component.ts 组件。下载完整的秘密英雄之旅app GitHub 仓库

敬请关注。 下周初我们将发布一个帖子,将指导您完成从零开始构建秘密英雄的旅游应用程序并将进一步讨论如何在Angular的应用的进行身份验证。

第 15 段(可获 1.39 积分)

结论

NgModule是一个伟大的和受欢迎的Angular2框架。 管理应用程序中的依赖关系从来不是一件容易的事,但是 @NgModule装饰是一个伟大的进步。如果你还没有在你的Angular2应用程序中使用它,,更新到 RC5 版本仅这一个功能就是值得的。如果您正在构建Angular2应用程序和做正确的身份验证,看看我们的 Angular 2 JWT 库 和登录会有一个免费的auth0账户用来启动和运行。

第 16 段(可获 1.2 积分)

文章评论