Angular4-學(xué)習(xí)筆記-1-邁出第一步

學(xué)習(xí)資料來自 Angular.cnAngular.io

雖然官方文檔很全面,但小鐳覺得官方文檔寫的很雜亂,重復(fù)的內(nèi)容很多。小鐳沒有到 Github 上細(xì)看,估計(jì)是很多人分別寫不同的部分最后匯總起來的。
該筆記將對(duì)官方文檔中的教程、指南、烹飪書等諸多內(nèi)容按照小鐳自己的思路和學(xué)習(xí)路線重新進(jìn)行整理,分享給每一個(gè)希望自學(xué) Angular 的朋友。

Angular 與 AngularJS 的差別非常大,無論是語法還是編寫方式。怪不得名字改了,讓小鐳感覺完全是兩個(gè)東西。
重新學(xué)吧 ! Angular 值得我們這樣做,因?yàn)樗浅:糜谩?/em>

快速起步

Angular 應(yīng)用由組件(components)組成。

組件包含:

  • HTML 模版(template)
  • 組件類(component class)
    組件類控制視圖。

組件樣例:src/app/app.component.ts

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

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

每個(gè)組件都以 @Component 裝飾器函數(shù)(decorator function)開始,它接受一個(gè)元數(shù)據(jù)對(duì)象(metadata object)參數(shù)。該元數(shù)據(jù)對(duì)象描述了 HTML 模板和組件類是如何一起工作的。

上例說明:

  • @Component({...}) 中的{}為元數(shù)據(jù)對(duì)象參數(shù)
  • selector 屬性為 Angular 指定了在 index.html 中的自定義 <my-app> 標(biāo)簽里顯示該組件
  • template 屬性定義了 <h1> 標(biāo)題里的一條消息
  • {{name}} 為插值綁定表達(dá)式(interpolation binding expression)

有關(guān)插值綁定表達(dá)式的更多知識(shí)見 顯示數(shù)據(jù)

頁(yè)面樣例:index.html

<body>
    <my-app>Loading AppComponent content here ...</my-app>
<body>

Angular 使用 TypeScript(基于效率考慮)。也可以使用 JavaScript,見指南。

教程: 英雄指南

英雄編輯器

該部分的在線例子。

準(zhǔn)備工作-本地環(huán)境搭建

參看頁(yè)面 搭建本地開發(fā)環(huán)境 并按照步驟操作即可。

安裝完種子包后,可參考 搭建剖析 了解文件夾內(nèi)各個(gè)文件的用途。

開始

小鐳直接利用上述種子包文件開始構(gòu)建項(xiàng)目。

保持應(yīng)用不斷轉(zhuǎn)譯和運(yùn)行

在命令行窗口中輸入:

npm start

該命令用途:

  • 在"監(jiān)聽"模式下運(yùn)行編譯器
  • 啟動(dòng)開發(fā)服務(wù)器
  • 在瀏覽器中啟動(dòng)應(yīng)用
  • 使應(yīng)用在后續(xù)構(gòu)建過程中能夠持續(xù)運(yùn)行

顯示英雄

小鐳的本地環(huán)境無法正常工作,應(yīng)用未成功加載,<my-app> 內(nèi)容未更新。

瀏覽器 Console 報(bào)錯(cuò)如下:

Error: (SystemJS) Block-scoped declarations 
(let, const, function, class) not yet supported outside strict mode

看來是 systemjs-angular-loader.js 文件出了問題。

在該文件首行加入如下代碼:

"use strict";

OK,問題解決。不過瀏覽器 Console 又有提示:

Angular is running in the development mode.
Call enableProdMode() to enable the production mode.

說明開發(fā)模式和生產(chǎn)模式是通過 enableProdMode() 方法來控制切換的。

那么如何使用這個(gè)方法呢?教程中居然沒有順帶提一句,唉……

其實(shí)我們只需要在 main.ts 中使用它就可以了,代碼如下:

import {enableProdMode} from '@angular/core';
enableProdMode();

此處使用該方法前一定要先 import 它,就像 platformBrowserDynamic() 方法一樣。

注意,上述代碼要放在 platformBrowserDynamic() 方法前使用,否則會(huì)報(bào)錯(cuò):

Error: (SystemJS) Cannot enable prod mode after platform setup.

OK,現(xiàn)在已經(jīng)知道如何切換工作模式了,現(xiàn)階段還是使用開發(fā)模式吧。

Hero 對(duì)象

此處需要注意的是代碼的位置。

如果 Hero 類插在了 @ComponentAppComponent 的中間,則會(huì)報(bào)錯(cuò):

Error: (SystemJS) Unexpected value 'AppComponent' declared by the module 'AppModule'. 
Please add a @Pipe/@Directive/@Component annotation.

@ComponentAppComponent 一定要連起來寫。所以應(yīng)該先讀一下 API 手冊(cè)中的相關(guān)內(nèi)容了解語法規(guī)則。

使用多行模板字符串添加更多 HTML

使用反引號(hào)``的模板字符串(也稱做——模板字面量,Template literals)。

樣例 app.component.ts (AppComponent's template)

template: `
  <h1>{{title}}</h1>
  <h2>{{hero.name}} details!</h2>
  <div><label>id: </label>{{hero.id}}</div>
  <div><label>name: </label>{{hero.name}}</div>
  `

編輯英雄名字

雙向綁定

1. 修改 app.module.ts 文件,導(dǎo)入 FormsModule 包:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms'; // <-- NgModel lives here
import { AppComponent }  from './app.component';
@NgModule({
  imports: [
    BrowserModule,
    FormsModule // <-- import the FormsModule before binding with [(ngModel)]
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

FormsModule 包中包含了 ngModel 指令,它用于雙向綁定。

關(guān)于 FormsModulengModel 的更多知識(shí),參見 表單模板語法

2. 更新模版

<div>
  <label>name: </label>
  <input [(ngModel)]="hero.name" placeholder="name">
</div>

該部分的在線例子鏈接。

主從結(jié)構(gòu)

該部分的在線例子。

*ngFor 語法

<li *ngFor="let hero of heroes">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

關(guān)于 *ngFor 和模板輸入變量的更多知識(shí),見顯示數(shù)據(jù)模板語法。

事件綁定例句

<li *ngFor="let hero of heroes" (click)="onSelect(hero)">
    ...
</li>

關(guān)于事件綁定的更多內(nèi)容,見用戶輸入模板語法。

*ngIf 語法

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

*ngIf*ngFor 被稱為“結(jié)構(gòu)型指令”。更多內(nèi)容見 結(jié)構(gòu)型指令模板語法

屬性綁定語法

[class.selected]="hero === selectedHero"

更多信息見模板語法。

多個(gè)組件

把主從結(jié)構(gòu)的頁(yè)面重構(gòu)成多個(gè)組件。每個(gè)子組件只聚焦在一個(gè)特定的任務(wù)或工作流上。 最后,AppComponent 將會(huì)變成一個(gè)簡(jiǎn)單的殼,用來作為那些子組件的宿主。

該部分重點(diǎn)是理解思想和概念。

該部分的在線例子。

遵循單一職責(zé)原則Wiki / 百度百科),創(chuàng)建復(fù)用組件。

文件名和組件名遵循風(fēng)格指南中的標(biāo)準(zhǔn)方式。

  • 組件的類名應(yīng)該是大駝峰形式,并且以 Component 結(jié)尾:HeroDetailComponent
  • 組件的文件名應(yīng)該是小寫中線形式,并且以 .component.ts 結(jié)尾:hero-detail.component.ts

命名約定:詞匯表-中線命名法
也稱為烤串命名法(kebab-case)。通常用于指令的選擇器和文件名。

Angular風(fēng)格指南建議每個(gè)文件中只有一個(gè)類。

輸入屬性與目標(biāo)屬性,參考屬性型指令相關(guān)內(nèi)容。

@Input() 裝飾器用來表明輸入屬性。更多信息參考屬性型指令相關(guān)內(nèi)容。

每個(gè)組件都必須在一個(gè)(且只有一個(gè))Angular 模塊中聲明。

樣例 src/app/app.module.ts

import { HeroDetailComponent } from './hero-detail.component';

更多知識(shí),參見 Angular 模塊頁(yè)。

服務(wù)

該部分的在線例子。

使用單獨(dú)的服務(wù)可以保持組件精簡(jiǎn),使其集中精力為視圖提供支持,并且,借助模擬(Mock)服務(wù),可以更容易的對(duì)組件進(jìn)行單元測(cè)試。

Injectable 函數(shù)

@Injectable() 裝飾器。注意不要忘記括號(hào),否則會(huì)導(dǎo)致一個(gè)很難診斷的錯(cuò)誤。

無論是出于提高統(tǒng)一性還是減少變更的目的, 都應(yīng)該從一開始就加上 @Injectable() 裝飾器。

術(shù)語:Method stub,方法存根

注入服務(wù)

  1. 添加一個(gè)構(gòu)造函數(shù),并定義一個(gè)私有屬性。
  2. 添加組件的 providers 元數(shù)據(jù)。

更多信息見依賴注入

注意構(gòu)造函數(shù)的功能,它的作用是簡(jiǎn)單的初始化工作,不要把復(fù)雜的邏輯放在構(gòu)造函數(shù)中。

ngOnInit 生命周期鉤子

Angular提供了一些接口,用來介入組件生命周期的幾個(gè)關(guān)鍵時(shí)間點(diǎn):剛創(chuàng)建時(shí)、每次變化時(shí),以及最終被銷毀時(shí)。

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

export class AppComponent implements OnInit {
  ngOnInit(): void {
  }
}

更多信息見生命周期鉤子

異步服務(wù)與承諾

樣例 src/app/hero.service.ts

getHeroes(): Promise<Hero[]> {
  return Promise.resolve(HEROES);
}

樣例 src/app/app.component.ts

getHeroes(): void {
  this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}

承諾與異步編程

ES2015箭頭函數(shù)(Lambda 表達(dá)式)

模擬慢速連接,可以據(jù)此觀察應(yīng)用在網(wǎng)絡(luò)較差情況下的表現(xiàn)。

getHeroesSlowly(): Promise<Hero[]> {
    return new Promise(resolve => {
        // Simulate server latency with 2 second delay
        setTimeout(() => resolve(this.getHeroes()), 2000);
    });
}

總結(jié)

教程就暫時(shí)進(jìn)行到這里。
教程里的路由這一章內(nèi)容較多,小鐳決定先通過官方文檔把目前接觸到的知識(shí)詳細(xì)地看一遍,深刻理解后再繼續(xù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容