在开始之前,我们需要在你的电脑上启动并运行种子项目

从Github克隆项目

  1. git clone git@github.com:gothinkster/angular2-realworld-example-app.git

克隆了repo之后,运行npm install来安装必要的依赖关系

查看种子分支(名为m-9)

  1. git checkout m-9

种子应用在开始时,你会看到一个共享文件夹,其中包含SharedModule和桶文件index.ts。在app.module.ts中导入SharedModule,使其可以被应用。种子应用是使用Angular的CLI工具生成的,然后我们为我们有点复杂的大型Web应用优化了文件结构。

要开始我们的项目,我们首先需要为Conduit应用构建基本的布局和路由。具体来说,我们需要设置路由器,设置好页眉和页脚,并创建一个主页。让我们从创建网站的页眉和页脚开始。

Angular风格指南规定,我们应该使用 “按功能文件夹 “的项目布局。例如,我们要在布局文件夹中创建Header和Footer组件,并在主页文件夹中创建Home组件。这就是Angular执行关注点分离的方式。

创建FooterComponent。你还需要创建shared文件夹和layout文件夹。

src/app/shared/layout/footer.component.html

  1. <footer>
  2. <div class="container">
  3. <a class="logo-font" routerLink="/">conduit</a>
  4. <span class="attribution">
  5. &copy; {{ today | date: 'yyyy' }}.
  6. An interactive learning project from <a href="https://thinkster.io">Thinkster</a>.
  7. Code licensed under MIT.
  8. </span>
  9. </div>
  10. </footer>

我们需要通过footer的组件类上的变量today来暴露当前日期。我们使用Angular的DatePipe来格式化当前的年份。

src/app/shared/layout/footer.component.ts

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'layout-footer',
  4. templateUrl: './footer.component.html'
  5. })
  6. export class FooterComponent {
  7. today: number = Date.now();
  8. }

接下来让我们为我们的网站创建头。

创建HeaderComponent

src/app/shared/layout/header.component.html

  1. <nav class="navbar navbar-light">
  2. <div class="container">
  3. <a class="navbar-brand" routerLink="/">conduit</a>
  4. <ul class="nav navbar-nav pull-xs-right">
  5. <li class="nav-item">
  6. <a class="nav-link"
  7. routerLink="/">
  8. Home
  9. </a>
  10. </li>
  11. <li class="nav-item">
  12. <a class="nav-link">
  13. Sign in
  14. </a>
  15. </li>
  16. <li class="nav-item">
  17. <a class="nav-link">
  18. Sign up
  19. </a>
  20. </li>
  21. </ul>
  22. </div>
  23. </nav>

src/app/shared/layout/header.component.ts

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'layout-header',
  4. templateUrl: './header.component.html'
  5. })
  6. export class HeaderComponent {
  7. constructor() {}
  8. }

允许这些组件在我们的应用程序中通过barrels轻松导入

在布局文件夹中创建一个barrell文件,并导出HeaderComponent和FooterComponent。
src/app/shared/layout/index.ts

  1. export * from './footer.component';
  2. export * from './header.component';

现在在shared文件夹中创建一个根barrell文件。导出我们的layout文件夹以方便访问。

src/app/shared/index.ts

  1. export * from './shared-module';
  2. + export * from './layout';

完美!接下来让我们创建我们的主页。接下来让我们创建我们的主页。在我们的应用程序目录中创建一个主页文件夹。

创建HomeComponent

src/app/home/home.component.html

  1. <div class="home-page">
  2. <div class="banner">
  3. <div class="container">
  4. <h1 class="logo-font">conduit</h1>
  5. <p>A place to share your <i>Angular</i> knowledge.</p>
  6. </div>
  7. </div>
  8. <div class="container page">
  9. <div class="row">
  10. <div class="col-md-9">
  11. <div class="feed-toggle">
  12. <ul class="nav nav-pills outline-active">
  13. <li class="nav-item">
  14. <a class="nav-link">
  15. Your Feed
  16. </a>
  17. </li>
  18. <li class="nav-item">
  19. <a class="nav-link">
  20. Global Feed
  21. </a>
  22. </li>
  23. </ul>
  24. </div>
  25. </div>
  26. <div class="col-md-3">
  27. <div class="sidebar">
  28. <p>Popular Tags</p>
  29. </div>
  30. </div>
  31. </div>
  32. </div>
  33. </div>

src/app/home/home.component.css

  1. .nav-link {
  2. cursor:pointer;
  3. }

而我们将这两者都导入到HomeComponent中。

src/app/home/home.component.ts

  1. import { Component } from '@angular/core';
  2. @Component({
  3. selector: 'home-page',
  4. templateUrl: './home.component.html',
  5. styleUrls: ['./home.component.css']
  6. })
  7. export class HomeComponent {
  8. constructor() {}
  9. }

我们的Home组件将作为导航的基础。app.module是应用程序的根,我们添加的任何其他页面组件都将是子组件。在这里,我们声明我们的基础导航是app.module的一个子模块。

创建HomeModule

src/app/home/home.module.ts

  1. import { ModuleWithProviders, NgModule } from '@angular/core';
  2. import { RouterModule } from '@angular/router';
  3. import { HomeComponent } from './home.component';
  4. import { SharedModule } from '../shared';
  5. const homeRouting: ModuleWithProviders = RouterModule.forChild([
  6. {
  7. path: '',
  8. component: HomeComponent
  9. }
  10. ]);
  11. @NgModule({
  12. imports: [
  13. homeRouting,
  14. SharedModule
  15. ],
  16. declarations: [
  17. HomeComponent
  18. ],
  19. providers: []
  20. })
  21. export class HomeModule {}

现在让我们把它整合起来

将HomeModule、HeaderComponent和FooterComponent导入到AppModule中,并声明应用程序的rootRouting

我们需要声明HeaderComponent和FooterComponent,以便在AppComponent的模板中使用它们(下一步会出现)。

src/app/app.module.ts

  1. import { ModuleWithProviders, NgModule } from '@angular/core';
  2. import { BrowserModule } from '@angular/platform-browser';
  3. +import { RouterModule } from '@angular/router';
  4. import { AppComponent } from './app.component';
  5. +import { HomeModule } from './home/home.module';
  6. import {
  7. SharedModule,
  8. + FooterComponent,
  9. + HeaderComponent,
  10. } from './shared';
  11. +const rootRouting: ModuleWithProviders = RouterModule.forRoot([], { useHash: true });
  12. @NgModule({
  13. declarations: [
  14. AppComponent,
  15. + FooterComponent,
  16. + HeaderComponent
  17. ],
  18. imports: [
  19. BrowserModule,
  20. SharedModule,
  21. + HomeModule,
  22. + rootRouting,
  23. ],
  24. providers: [],
  25. [...]

最后,我们只需要将HeaderComponent和FooterComponent放置在router-outlet的上方和下方,我们的路由将被渲染到那里。

将AppComponent模板替换为我们的布局组件和一个**router-outlet**

src/app/app.component.html

  1. <layout-header></layout-header>
  2. <router-outlet></router-outlet>
  3. <layout-footer></layout-footer>

在你的浏览器中,你现在应该可以看到主页呈现在页眉和页脚组件之间了。

你可以在Github上查看有效代码,或者在本地检查分支:

  1. git checkout m-8