Angular cli-1
Angular 腳手架的腳本是 TypeScript
環境搭建
使用 node.js
配置 Angular-cli
的環境。
命令:
npm install -g @angular/cli
創建新的項目
ng new my-app
ng new
命令執行時,會提示要把哪些特性添加到應用中,按 Enter
或 Return
鍵可以接收默認值。
運行項目
cd my-app
ng serve --open
目錄結構簡介
# 一級目錄介紹
node_modules:
第三方依賴包存放目錄
e2e
端到端的測試目錄 用來做自動測試的
src
應用源代碼目錄
angular.json
Angular命令行工具的配置文件。後期可能會去修改它,引一些其他的第三方的包
karma.conf.js
karma是單元測試的執行器,karma.conf.js是karma的配置文件
package.json
是一個標準的npm工具的配置文件,這個文件裏面列出了該應用程序所使用的第三方依賴包。實際上我們在新建項目的時候,等了半天就是在下載第三方依賴包。下載完成後會放在node_modules這個目錄中,後期我們可能會修改這個文件。
README.md
說明文件
tslint.json
是tslint的配置文件,用來定義TypeScript代碼質量檢查的規則,不用管它
# src目錄介紹
app目錄
包含應用的組件和模塊
assets目錄
資源目錄,存儲靜態資源的 比如圖片
environments目錄
環境配置。Angular是支持多環境開發的,我們可以在不同的環境下(開發環境,測試環境,生產環境)共用一套代碼,主要用來配置環境的
index.html
整個應用的根html,程序啓動就是訪問這個頁面
main.ts
整個項目的入口點,Angular通過這個文件來啓動項目
polyfills.ts
主要是用來導入一些必要庫,爲了讓Angular能正常運行在老版本下
styles.css
主要是放一些全局的樣式
組件
一、創建組件和目錄結構
在項目的命令行輸入創建一個組件 LeftMenu
的命令:
ng generate component LeftMenu
app
目錄下會自動生成組件的相關文件:
left-menu.component.css
當前組件的css
left-menu.component.html
當前組件的html
left-menu.component.spec.ts
當前組件的測試文件
left-menu.component.ts
當前組件的腳本
二、組件的腳本
一個組件被創建好之後,它的腳本代碼中會有一些默認生成的內容:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-left-menu',
// 當前組建類結構的路徑
templateUrl: './left-menu.component.html',
// 當前組建類樣式的路徑
styleUrls: ['./left-menu.component.css']
})
export class LeftMenuComponent implements OnInit {
// 導出當前組建類,在類中定義組件的應用邏輯,爲視圖提供支持。 組件通過一些由屬性和方法組成的 API 與視圖交互
// 組建類的構造函數
constructor() { }
// 組建類初始化的生命週期鉤子函數
ngOnInit() {
}
}
@Component 詳解
@Component
是一個裝飾器,繪指出緊隨其後的這個類是個組建類(當前示例中爲 LeftMenuComponent
),並規定其元數據。
如果一個類沒有被 @Component
裝飾器修飾,那麼這個類就是個普通的類,不代表任意組件,你只能使用這個類完成基礎的 JS 邏輯交互。
- selector: 是一個
CSS
選擇器,他會告訴Angular
,一旦在模板 HTML 中找到了這個選擇器對應的標籤,就創建並插入該組件的一個實例。 比如,如果應用的HTML
中包含<app-left-menu></app-left-menu>
,Angular
就會在這些標籤中插入一個 ``LeftMenuComponent` 實例的視圖。 - templateUrl: 該組件的
HTML
模板文件相對於這個組件文件的地址。 另外,你還可以用template
屬性的值來提供內聯的HTML
模板。 這個模板定義了該組件的宿主視圖。 - styleUrls: 作用於當前組件的所有的樣式列表。
一個組件被創建之後可以在任意組件中直接使用組件的 @Component
中的 selector
調用組件
組件的數據渲染和事件綁定
一、組件的數據聲明
// left-menu.component.ts
import { Component } from '@angular/core'
@Component({
selector: 'app-left-menu',
templateUrl: './left-menu.component.html'
})
export class LeftMenuComponent {
// 方式一
title = '菜單欄';
list = ['孫權', '周瑜', '魯肅', '呂蒙', '陸遜'];
className = 'active';
// 方式二
flag: boolean;
constructor() {
this.flag = true;
}
ngOnInit() {}
onBtnClick() {
this.flag = false;
}
}
通過不同方式聲明的組件的數據,意義和使用方式都是相同的。
二、數據綁定
Angular
支持雙向數據綁定,這是一種對模板中的各個部件與組件中的各個部件進行協調的機制。 往模板 HTML 中添加綁定標記可以告訴 Angular 該如何連接它們。
1. 插值表達式
<!-- left-menu.component.html -->
<h1>{{ title }}</h1>
<h2>{{ flag ? '海子' : '三體' }}</h2>
<h3>{{ flag && '仙逆' }}</h3>
2. 屬性中動態的綁定數據
<!-- left-menu.component.html -->
<h1 [class]="className">{{ title }}</h1>
<input [value]="list[0]" />
3. 將組建類的函數綁定給組件中的某個事件
<!-- left-menu.component.html -->
<button (click)="onBtnClick()">點我</button>
4. 雙向數據綁定
雙向數據綁定主要應用於模板驅動表單中。Angular
提供了 ngModel
指令實現數據雙向綁定。
但是要使用 ngModel
需要在導入 FormsModule
包:
// app.module.ts
...
import {FormsModule} from '@angular/forms';
@NgModule({
...
imports: [
...
FormsModule
]
...
})
export class AppModule { }
<!-- left-menu.component.html -->
<input [(ngModel)]="title" />
三、管道修飾符
我們可以把管道理解爲數據過濾器。
Angular
的管道可以讓你在模板中聲明顯示值的轉換邏輯。 帶有 @Pipe
裝飾器的類中會定義一個轉換函數,用來把輸入值轉換成供視圖顯示用的輸出值。
Angular
自帶了很多管道,比如 date
管道和 currency
管道。
你可以把管道串聯起來,把一個管道函數的輸出送給另一個管道函數進行轉換。 管道還能接收一些參數,來控制它該如何進行轉換。比如,你可以把要使用的日期格式傳給 date 管道:
<!-- Default format: output 'Jun 15, 2015'-->
<p>Today is {{1566635864356 | date}}</p>
<!-- fullDate format: output 'Monday, June 15, 2015'-->
<p>The date is {{1566635864356 | date:'fullDate'}}</p>
<!-- shortTime format: output '9:43 AM'-->
<p>The time is {{1566635864356 | date:'shortTime'}}</p>
四、數據渲染的指令
Angular
的模板是動態的。當 Angular
渲染它們的時候,會根據指令給出的指示對 DOM
進行轉換。 指令就是一個帶有 @Directive()
裝飾器的類。
組件從技術角度上說就是一個指令,但是由於組件對 Angular 應用來說非常獨特、非常重要,因此 Angular
專門定義了 @Component()
裝飾器,它使用一些面向模板的特性擴展了 @Directive()
裝飾器。
除組件外,還有兩種指令:結構型指令(ngFor,ngIf) 和 屬性型指令( [(ngModel)] 就是一個屬性型指令)。 Angular
本身定義了一系列這兩種類型的指令,你也可以使用 @Directive()
裝飾器來定義自己的指令。
像組件一樣,指令的元數據把它所裝飾的指令類和一個 selector
關聯起來,selector
用來把該指令插入到 HTML 中。 在模板中,指令通常作爲屬性出現在元素標籤上,可能僅僅作爲名字出現,也可能作爲賦值目標或綁定目標出現。
結構型指令通過添加、移除或替換 DOM 元素來修改佈局。 這個範例模板使用了兩個內置的結構型指令來爲要渲染的視圖添加程序邏輯
簡單示例:
1. ngFor
<!-- left-menu.component.html -->
<ul>
<!--
list 爲組件類中聲明的數據
item 相當於此次循環的一個局部變量,代表每次循環到的數據
-->
<li *ngFor="let item of list">{{ item }}</li>
</ul>
2. ngIf
<!-- left-menu.component.html -->
<h1 *ngIf="flag">{{ title }}</h1>
組件間的數據交互
Angular 提供了 @Input,@Output 和 @ViewChild 來實現組件之間的數據通信
示例需求,實現父級組件 Father
和 子級組件 Kid
之間的數據交互。
一、父傳子(@Input)
// father.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-father',
templateUrl: './father.component.html',
styleUrls: ['./father.component.css']
})
export class FatherComponent implements OnInit {
tip = '我是來自父組件的數據';
constructor() { }
// 父組件中的函數
fnOfFather() {
/*
*****
當前組件調用該函數,this 爲當前組建類
如果將當前函數傳遞給子組件,在子組件中調,this 指向自組建類
*/
console.log('fnOfFather');
console.log(this.title);
}
ngOnInit() {
}
}
<!-- father.component.html -->
<!--
在父組件中調用 Kid 子組件
msg 和 fn是 傳遞給子組件的數據指針,子組件通過這個指針接受數據
如果 msg 不需要讀取變量 tip 的值,那 msg 不需要加 [] 修飾
-->
<app-kid [msg]="tip" [fn]="fnOfFather"></app-kid>
子組件中要接收
// kid.component.ts
// 導入 @Input 裝飾器
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-kid-content',
templateUrl: './kid-content.component.html',
styleUrls: ['./kid-content.component.css']
})
export class KidComponent implements OnInit {
// 通過 @Input 裝飾器接收數據,接收之後可以直接加以使用
@Input()msg: string;
@Input()fn: any;
constructor() { }
ngOnInit() {
this.fn(); // 調用 fn 會執行 Father 中的 fnOfFather 函數
}
}
<!-- kid.component.html -->
<h1>{{ msg }}</h1>
二、子傳父(@Output 和 EventEmitter)
點擊 <Kid>
組件中的某個按鈕,向父級組件傳遞一個數據。
<!-- kid.component.html -->
<!--
點擊按鈕時,調用當前組件的 toFather 函數
-->
<button (click)="toFather()">傳值</button>
// kid.component.ts 導入傳參需要使用的 @Output 裝飾器和 EventEmitter 類
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'kid-menu',
templateUrl: './kid.component.html',
styleUrls: ['./kid.component.css']
})
export class KidComponent implements OnInit {
// 創建一個 EventEmitter 對象
// 並規定使用這個對象的 emit 函數導出事件時,參數爲一個對象
// 將這個對象定義成當前類的私有屬性,並使用 @Output 裝飾器修飾
@Output() private outer = new EventEmitter<object>();
list = ['孫權', '周瑜', '魯肅', '呂蒙', '陸遜'];
ngOnInit() {
this.fn();
}
toFather() {
this.outer.emit(this.list);
}
}
父組件調用子組件時,需要預留接口接受子組件通過事件傳遞的參數:
<!-- father.component.html -->
<!--
使用當前組件中的 fn 函數和 $event 對象,接受子組件觸發事件時導出的事件及參數
-->
<app-kid (outer)="fn($event)"></app-kid>
// father.component.ts
// ...
export class CenterContentComponent implements OnInit {
fn(param) {
// 當子組件中的傳值按鈕被點擊時,父組件中的 fn 函數會被自動調用
// param 是子組件觸發事件的同事傳遞過來的參數
console.log(param);
}
ngOnInit() {
}
}