Angular 4 快速入門

建了個羣有興趣的朋友能夠加一下 QQ 羣:Angular 修仙之路(1)羣 - 153742079 (已滿),請加 Angular 修仙之路(2)羣 - 648681235。

目錄

  • 第一節 - Angular 簡介
  • 第二節 - Angular 環境搭建
  • 第三節 - 插值表達式
  • 第四節 - 自定義組件
  • 第五節 - 經常使用指令簡介
  • 第六節 - 事件綁定
  • 第七節 - 表單模塊簡介
  • 第八節 - Http 模塊簡介
  • 第九節 - 注入服務
  • 第十節 - 路由模塊簡介
查看新版教程,請訪問 Angular 6.x 快速入門

第一節 Angular 簡介

Angular 是什麼

Angular 是由谷歌開發與維護一個開發跨平臺應用程序的框架,同時適用於手機與桌面。html

Angular 有什麼特色

  • 基於 Angular 咱們能夠構建適用於全部平臺的應用。好比:Web 應用、移動 Web 應用、移動應用和桌面應用等。
  • 經過 Web Worker和服務端渲染 (SSR),達到在現在Web平臺上所能達到的最高渲染速度。
  • Angular 讓你可以有效掌控可伸縮性。基於 RxJS、Immutable.js 和其它推送模型,能適應海量數據需求。

Angular 提供了哪些功能

  • 動態HTML
  • 強大的表單系統 (模板驅動和模型驅動)
  • 強大的視圖引擎
  • 事件處理
  • 快速的頁面渲染
  • 靈活的路由
  • HTTP 服務
  • 視圖封裝
  • AOT、Tree Shaking

Angular 與 AngularJS 有什麼區別

  • 再也不有ControllerScope
  • 更好的組件化及代碼複用
  • 更好的移動端支持
  • 引入了 RxJSObservable
  • 引入了 Zone.js,提供更加智能的變化檢測

第二節 - Angular 環境搭建

基礎要求

Angular 開發環境配置方式

配置開發環境

本快速入門教程,選用第一種配置方式搭建 Angular 開發環境:github

基於 Angular Quickstart

  • 使用 Git 克隆 quickstart 項目
git clone https://github.com/angular/quickstart ng4-quickstart
code ./ng4-quickstart
  • 安裝項目所需依賴
npm i
  • 驗證環境是否搭建成功
npm start

基於 Angular CLI

npm install -g @angular/cli
  • 檢測 Angular CLI 是否安裝成功
ng --version
  • 建立新的項目
ng new PROJECT-NAME
  • 啓動本地服務器
cd PROJECT-NAME
ng serve

第三節 - 插值表達式

在 Angular 中,咱們可使用 {{}} 插值語法實現數據綁定。typescript

綁定普通文本

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

@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>`,
})
export class AppComponent  {
  name = 'Angular'; 
}

綁定對象屬性

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

@Component({
  selector: 'my-app',
  template: `
    <h2>你們好,我是{{name}}</h2>
    <p>我來自<strong>{{address.province}}</strong>省,
      <strong>{{address.city}}</strong>市
    </p>
  `,
})
export class AppComponent {
  name = 'Semlinker';
  address = {
    province: '福建',
    city: '廈門'
  }
}

值得一提的是,咱們可使用 Angular 內置的 json 管道,來顯示對象信息:shell

@Component({
  selector: 'my-app',
  template: `
    ...
    <p>{{address | json}}</p>
  `,
})
export class AppComponent {
  name = 'Semlinker';
  address = {
    province: '福建',
    city: '廈門'
  }
}

第四節 - 自定義組件

在 Angular 中,咱們能夠經過 Component 裝飾器和自定義組件類來建立自定義組件。npm

基礎知識

定義組件的元信息

在 Angular 中,咱們可使用 Component 裝飾器來定義組件的元信息:json

@Component({
  selector: 'my-app', // 用於定義組件在HTML代碼中匹配的標籤
  template: `<h1>Hello {{name}}</h1>`, // 定義組件內嵌視圖
})

定義組件類

export class AppComponent  {
  name = 'Angular'; 
}

定義數據接口

在 TypeScript 中的接口是一個很是靈活的概念,除了可用於對類的一部分行爲進行抽象之外,也經常使用於對「對象的形狀(Shape)」進行描述。bootstrap

interface Person {
  name: string;
  age: number;
}

let semlinker: Person = {
  name: 'semlinker',
  age: 31
};

自定義組件示例

建立 UserComponent 組件

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

@Component({
    selector: 'sl-user',
    template: `
    <h2>你們好,我是{{name}}</h2>
    <p>我來自<strong>{{address.province}}</strong>省,
      <strong>{{address.city}}</strong>市
    </p>
    `
})
export class UserComponent {
    name = 'Semlinker';
    address = {
        province: '福建',
        city: '廈門'
    };
}

聲明 UserComponent 組件

// ...
import { UserComponent } from './user.component';
@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent, UserComponent],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

使用 UserComponent 組件

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

@Component({
  selector: 'my-app',
  template: `
    <sl-user></sl-user>
  `,
})
export class AppComponent {}

使用構造函數初始化數據

@Component({...})
export class UserComponent {
    name: string;
    address: any;

    constructor() {
        this.name = 'Semlinker';
        this.address = {
            province: '福建',
            city: '廈門'
        }
    }
}

接口使用示例

定義 Address 接口

interface Address {
    province: string;
    city: string;
}

使用 Address 接口

export class UserComponent {
    name: string;
    address: Address;
    // ...
}

第五節 - 經常使用指令簡介

在 Angular 實際項目中,最經常使用的指令是 ngIfngFor 指令。segmentfault

基礎知識

ngIf 指令簡介

該指令用於根據表達式的值,動態控制模板內容的顯示與隱藏。它與 AngularJS 1.x 中的 ng-if 指令的功能是等價的。

ngIf 指令語法

<div *ngIf="condition">...</div>

ngFor 指令簡介

該指令用於基於可迭代對象中的每一項建立相應的模板。它與 AngularJS 1.x 中的 ng-repeat 指令的功能是等價的。

ngFor 指令語法

<li *ngFor="let item of items;">...</li>

ngIf 與 ngFor 指令使用示例

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

interface Address {
    province: string;
    city: string;
}

@Component({
    selector: 'sl-user',
    template: `
    <h2>你們好,我是{{name}}</h2>
    <p>我來自<strong>{{address.province}}</strong>省,
      <strong>{{address.city}}</strong>市
    </p>
    <div *ngIf="showSkills">
        <h3>個人技能</h3>
        <ul>
            <li *ngFor="let skill of skills">
                {{skill}}
            </li>
        </ul>
    </div>
    `
})
export class UserComponent {
    name: string;
    address: Address;
    showSkills: boolean;
    skills: string[];

    constructor() {
        this.name = 'Semlinker';
        this.address = {
            province: '福建',
            city: '廈門'
        };
        this.showSkills = true;
        this.skills = ['AngularJS 1.x', 'Angular 2.x', 'Angular 4.x'];
    }
}

第六節 - 事件綁定

在 Angular 中,咱們能夠經過 (eventName) 的語法,實現事件綁定。

基礎知識

事件綁定語法

<date-picker (dateChanged)="statement()"></date-picker>

等價於

<date-picker on-dateChanged="statement()"></date-picker>

介紹完事件綁定的語法,接下來咱們來爲第五節中的 UserComponent 組件,開發一個功能,便可以讓用戶動態控制技能信息的顯示與隱藏。

事件綁定示例

@Component({
    selector: 'sl-user',
    template: `
    ...
    <button (click)="toggleSkills()">
        {{ showSkills ? "隱藏技能" : "顯示技能" }}
    </button>
    ...
    `
})
export class UserComponent {
    // ...
    toggleSkills() {
        this.showSkills = !this.showSkills;
    }
}

第七節 - 表單模塊簡介

Angular 中有兩種表單:

  • Template Driven Forms - 模板驅動式表單 (相似於 AngularJS 1.x 中的表單 )
  • Reactive Forms - 響應式表單

本小節主要介紹模板驅動式的表單,接下來咱們來演示如何經過表單來爲咱們的以前建立的 UserComponent 組件,增長讓用戶自定義技能的功能。

基礎知識

導入表單模塊

import { FormsModule } from '@angular/forms';
// ...
@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent, UserComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

模板變量語法

<video #player></video> 
<button (click)="player.pause()">Pause</button>

等價於

<video ref-player></video>

表單使用示例

@Component({
    selector: 'sl-user',
    template: `
    ...
    <div *ngIf="showSkills">
        <h3>個人技能</h3>
        ...
        <form (submit)="addSkill(skill.value)">
            <label>添加技能</label>
            <input type="text" #skill>
        </form>
    </div>
    `
})
export class UserComponent {
   // ...
    addSkill(skill: string) {
        let skillStr = skill.trim();
        if (this.skills.indexOf(skillStr) === -1) {
            this.skills.push(skillStr);
        }
    }
}

第八節 - Http 模塊簡介

Angular 4.3 版本後,推薦使用 HttpClient,能夠參考 Angular HTTP Client 快速入門

基礎知識

導入 Http 模塊

// ... 
import { HttpModule } from '@angular/http';

@NgModule({
  imports: [BrowserModule, FormsModule, HttpModule],
  declarations: [AppComponent, UserComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

使用 Http 服務步驟

(1) 從 @angular/http 模塊中導入 Http 類

(2) 導入 RxJS 中的 map 操做符

(3) 使用 DI 方式注入 http 服務

(4) 調用 http 服務的 get() 方法,設置請求地址併發送 HTTP 請求

(5) 調用 Response 對象的 json() 方法,把響應體轉成 JSON 對象

(6) 把請求的結果,賦值給對應的屬性

Http 服務使用示例

使用 Http 服務

import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http'; // (1)
import 'rxjs/add/operator/map'; // (2)

interface Member {
    id: string;
    login: string;
    avatar_url: string;
}

@Component({
    selector: 'sl-members',
    template: `
    <h3>Angular Orgs Members</h3>
    <ul *ngIf="members">
      <li *ngFor="let member of members;">
        <p>
          <img [src]="member.avatar_url" width="48" height="48"/>
          ID:<span>{{member.id}}</span>
          Name: <span>{{member.login}}</span>
        </p>
      </li>
    </ul>
    `
})
export class MembersComponent implements OnInit {
  members: Member[];

  constructor(private http: Http) { } // (3)

  ngOnInit() {
    this.http.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`) // (4)
        .map(res => res.json()) // (5)
        .subscribe(data => {
           if (data) this.members = data; // (6)
        });
    }
}

聲明 MembersComponent 組件

// ...
import { MembersComponent } from './members.component';

@NgModule({
  imports: [BrowserModule, FormsModule, HttpModule],
  declarations: [AppComponent, UserComponent, MembersComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

使用 MembersComponent 組件

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

@Component({
  selector: 'my-app',
  template: `
    <sl-members></sl-members>
  `,
})
export class AppComponent {}

第九節 - 注入服務

基礎知識

組件中注入服務步驟

(1) 配置已建立的服務,如:

@NgModule({
  // ...
  providers: [MemberService]
})
export class AppModule { }

(2) 導入已建立的服務,如:

import { MemberService } from '../member.service';

(3) 使用構造注入方式,注入服務:

export class MembersComponent implements OnInit {
   // ...
   constructor(private memberService: MemberService) { }
}

服務使用示例

建立 MemberService 服務

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class MemberService {
    constructor(private http: Http) { }

    getMembers() {
        return this.http
            .get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)
            .map(res => res.json())
    }
}

配置 MemberService 服務

import { MemberService } from "./member.service";

@NgModule({
  // ...
  providers:[MemberService],
  bootstrap: [AppComponent]
})
export class AppModule { }

使用 MemberService 服務

// ...
import { MemberService } from "./member.service";

@Component({...})
export class MembersComponent implements OnInit {
    members: Member[];

    constructor(private memberService: MemberService) { }

    ngOnInit() {
        this.memberService.getMembers()
            .subscribe(data => {
                if (data) this.members = data;
            });
    }
}

第十節 - 路由模塊簡介

基礎知識

導入路由模塊

// ...
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [BrowserModule, FormsModule, HttpModule, RouterModule],
  declarations: [AppComponent, UserComponent, MembersComponent],
  bootstrap: [AppComponent]
})
export class AppModule { }

配置路由信息

import { Routes, RouterModule } from '@angular/router';
import { UserComponent } from './user.component';

export const ROUTES: Routes = [
  { path: 'user', component: UserComponent }
];

@NgModule({
  imports: [
    BrowserModule,
    RouterModule.forRoot(ROUTES)
  ],
  // ...
})
export class AppModule {}

routerLink 指令

爲了讓咱們連接到已設置的路由,咱們須要使用 routerLink 指令,具體示例以下:

<nav>
  <a routerLink="/">首頁</a>
  <a routerLink="/user">個人</a>
</nav>

當咱們點擊以上的任意連接時,頁面不會被從新加載。反之,咱們的路徑將在 URL 地址欄中顯示,隨後進行後續視圖更新,以匹配 routerLink 中設置的值。

router-outlet 指令

該指令用於告訴 Angular 在哪裏加載組件,當 Angular 路由匹配到響應路徑,併成功找到須要加載的組件時,它將動態建立對應的組件,並將其做爲兄弟元素,插入到 router-outlet 元素中。具體示例以下:

@Component({
  selector: 'app-root',
  template: `
    <div class="app">
      <h3>Our app</h3>
      <router-outlet></router-outlet>
    </div>
  `
})
export class AppComponent {}

路由使用示例

配置路由信息

export const ROUTES: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'user' },
  { path: 'user', component: UserComponent },
  { path: 'members', component: MembersComponent }
];

@NgModule({
  imports: [BrowserModule, FormsModule, HttpModule,
    RouterModule.forRoot(ROUTES)],
  // ...
})
export class AppModule { }

配置路由導航

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

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      <h1>歡迎來到Angular的世界</h1>
      <nav>
        <a routerLink="/user">個人</a>
        <a routerLink="/members">Angular成員</a>
      </nav>
      <router-outlet></router-outlet>
    </div>
  `,
})
export class AppComponent { }

完整示例

AppModule

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { UserComponent } from './user.component';
import { MembersComponent } from './members.component';
import { MemberService } from "./member.service";

export const ROUTES: Routes = [
  { path: '', pathMatch: 'full', redirectTo: 'user' },
  { path: 'user', component: UserComponent },
  { path: 'members', component: MembersComponent }
];

@NgModule({
  imports: [BrowserModule, FormsModule, HttpModule,
    RouterModule.forRoot(ROUTES)],
  declarations: [AppComponent, UserComponent, MembersComponent],
  providers: [MemberService],
  bootstrap: [AppComponent]
})
export class AppModule { }

AppComponent

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

@Component({
  selector: 'my-app',
  template: `
    <div class="app">
      <h1>歡迎來到Angular的世界</h1>
      <nav>
        <a routerLink="/user">個人</a>
        <a routerLink="/members">Angular成員</a>
      </nav>
      <router-outlet></router-outlet>
    </div>
  `,
})
export class AppComponent { }

UserComponent

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


interface Address {
    province: string;
    city: string;
}

@Component({
    selector: 'sl-user',
    template: `
    <h2>你們好,我是{{name}}</h2>
    <p>我來自<strong>{{address.province}}</strong>省,
      <strong>{{address.city}}</strong>市
    </p>
    <button (click)="toggleSkills()">
        {{ showSkills ? "隱藏技能" : "顯示技能" }}
    </button>
    <div *ngIf="showSkills">
        <h3>個人技能</h3>
        <ul>
            <li *ngFor="let skill of skills">
                {{skill}}
            </li>
        </ul>
        <form (submit)="addSkill(skill.value)">
            <label>添加技能</label>
            <input type="text" #skill>
        </form>
    </div>
    `
})
export class UserComponent {
    name: string;
    address: Address;
    showSkills: boolean;
    skills: string[];

    constructor() {
        this.name = 'Semlinker';
        this.address = {
            province: '福建',
            city: '廈門'
        };
        this.showSkills = true;
        this.skills = ['AngularJS 1.x', 'Angular 2.x', 'Angular 4.x'];
    }

    toggleSkills() {
        this.showSkills = !this.showSkills;
    }

    addSkill(skill: string) {
        let skillStr = skill.trim();
        if (this.skills.indexOf(skillStr) === -1) {
            this.skills.push(skillStr);
        }
    }
}

MembersComponent

import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

import { MemberService } from "./member.service";

interface Member {
    id: string;
    login: string;
    avatar_url: string;
}

@Component({
    selector: 'sl-members',
    template: `
    <h3>Angular Orgs Members</h3>
    <ul *ngIf="members">
      <li *ngFor="let member of members;">
        <p>
          <img [src]="member.avatar_url" width="48" height="48"/>
          ID:<span>{{member.id}}</span>
          Name: <span>{{member.login}}</span>
        </p>
      </li>
    </ul>
    `
})
export class MembersComponent implements OnInit {
    members: Member[];

    constructor(private memberService: MemberService) { }

    ngOnInit() {
        this.memberService.getMembers()
            .subscribe(data => {
                if (data) this.members = data;
            });
    }
}

MemberService

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class MemberService {
    constructor(private http: Http) { }

    getMembers() {
        return this.http
            .get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)
            .map(res => res.json())
    }
}

我有話說

除了本系列教程外,還有其它學習資源麼?

本系列教程的主要目的是讓初學者對 Angular 的相關基礎知識,有必定的瞭解。除了本系列教程外,初學者還能夠參考如下教程:

相關文章
相關標籤/搜索