Angular學習筆記-深入學習

Angular 有什麼特點

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

在 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())
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章