Angular 4 快速入門

查看新版教程,請訪問 Angular 6.x 快速入門

目錄

  • 第一節 - Angular 簡介
  • 第二節 - Angular 環境搭建
  • 第三節 - 插值表達式
  • 第四節 - 自定義組件
  • 第五節 - 常用指令簡介
  • 第六節 - 事件綁定
  • 第七節 - 表單模塊簡介
  • 第八節 - Http 模塊簡介
  • 第九節 - 注入服務
  • 第十節 - 路由模塊簡介

第一節 Angular 簡介

Angular 是什么

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

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 開發環境:

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

第三節 - 插值表達式

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

綁定普通文本

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 管道,來顯示對象信息:

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

第四節 - 自定義組件

在 Angular 中,我們可以通過 Component 裝飾器和自定義組件類來創建自定義組件。

基礎知識

定義組件的元信息

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

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

定義組件類

export class AppComponent  {
  name = 'Angular'; 
}

定義數據接口

在 TypeScript 中的接口是一個非常靈活的概念,除了可用于對類的一部分行為進行抽象以外,也常用于對「對象的形狀(Shape)」進行描述。

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 指令。

基礎知識

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 模塊簡介

基礎知識

導入 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 的相關基礎知識,有一定的了解。除了本系列教程外,初學者還可以參考以下教程:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,991評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,523評論 25 708
  • 路由是 Angular 應用程序的核心,它加載與所請求路由相關聯的組件,以及獲取特定路由的相關數據。這允許我們通過...
    semlinker閱讀 12,208評論 4 16
  • 你一定來過 是千百個夢里的一回 余暉殘影中的一瞥 不求你記得我,但我知道你來過 來過,是匆匆的腳步 到千里之外去,...
    跟住閱讀 246評論 0 2
  • 如果人生是一所大學,那么我們需要學習各種課程。 找工作,戀愛,賺錢等等,是很多人必修的課程。英語,寫作,健身,投資...
    銀河星海閱讀 805評論 3 4