屬性、元素操做以及指令普通數據圖片展現模板引用變量NgForNgSwitch和NgIfNgClass和NgStyle管道安全導航運算符( `?` )和空屬性路徑綁定語法綁定類型與綁定目標事件普通點擊事件表單事件雙向數據綁定$event 和事件處理語句Form表單搜索TodoList(待辦事項和已完成事項)javascript
新建 news 組件,首先在 news.component.ts 文件中定義變量:css
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-news',
templateUrl: './news.component.html',
styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
title = 'Hello hresh';
public name: any = 'hresh';
content: any = '<h3>Hello Java</h3>';
msg = '中國,你好';
constructor() {
this.msg = '你好中國';
}
ngOnInit(): void {
}
}
複製代碼
在 html 文件中定義標籤來獲取定義的變量並顯示:html
<div>
<p>news works!</p>
<!--數據文本綁定-->
<h3>{{title}}</h3>
<hr />
<h1>{{content}}</h1>
<br>
<!--綁定 html-->
<span [innerHTML]="content"></span>
<br>
<h2>{{msg}}</h2>
<br>
1+1={{1+1}}
</div>
複製代碼
效果圖以下:java
圖片資源能夠是本地資源,也能夠從網上獲取,在 html 文件中作以下配置:nginx
<h3>引入圖片</h3>
<img src="assets/images/10001.png" alt="hello" />
<hr>
<img [src]="picUrl" />
<img src="{{picUrl}}" />
複製代碼
本地靜態資源存放位置以下:web
網上圖片資源連接能夠在 argular01.component.ts 中定義:json
public picUrl = 'https://cn.bing.com/th?id=OIP.bbd7bi181qua_NdZzguE3QHaE6&pid=Api&rs=1';
複製代碼
網頁展現圖以下:bootstrap
模板引用變量 一般是對模板中 DOM 元素的引用。它還能夠引用指令(包含組件)、元素、TemplateRef 或 Web Component 。 後端
使用井號(#)聲明模板引用變量。如下模板引用變量 #phone
會在 input
元素上聲明瞭一個 phone
變量。 api
<input #phone placeholder="phone number" />
<!-- lots of other elements -->
<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
複製代碼
模板引用變量的範圍是整個模板。所以,不要在同一模板中屢次定義相同的變量名,由於它在運行時的值將不可預測。
替代語法
你也能夠用 ref-
前綴代替 #
。 下面的例子中就用把 fax
變量聲明成了 ref-fax
而不是 #fax
。
<input ref-fax placeholder="fax number" />
<button (click)="callFax(fax.value)">Fax</button>
複製代碼
ngFor
指令迭代父組件的 items
屬性所返回的 items
數組,並在每次迭代期間將 item
設置爲該數組中的當前條目。 NgFor
指令上下文中的 index
屬性在每次迭代中返回該條目的從零開始的索引。 您能夠在模板輸入變量中捕獲 index
,並在模板中使用它。
一樣在 news 組件中,首先定義數組內容:
nums: any[] = [111, 2222, 333];
public values: Array<string> = ['111', '222', '333'];
userList: any[] = [
{
name : 'hresh',
age : 22
},
{
name : 'hresh2',
age : 22
},
{
name : 'hresh3',
age : 22
}
]
cars: any[] = [
{
name: '寶馬',
list: [
{
title: 'x1',
price: '30萬'
},
{
title: 'x2',
price: '30萬'
},
{
title: 'x3',
price: '30萬'
}
]
},
{
name: '奔馳',
list: [
{
title: 'x1',
price: '30萬'
},
{
title: 'x2',
price: '30萬'
},
{
title: 'x3',
price: '30萬'
}
]
}
]
複製代碼
在 html 文件中添加內容:
<ul>
<li *ngFor="let item of nums">
{{item}}
</li>
</ul>
<br>
<ul>
<li *ngFor="let item of userList">
{{item.name}}---{{item.age}}
</li>
</ul>
<br>
<ul>
<li *ngFor="let item of cars">
{{item.name}}
<ul>
<li *ngFor="let car of item.list">
{{car.title}}----{{car.price}}
</li>
</ul>
</li>
</ul>
複製代碼
效果以下:
帶 trackBy
的 *ngFor
好比有這樣一個例子:
import{ Component } from '@angular/core';
@Component({
selector: 'trackBy-test',
template: `
<ul><li *ngFor="let item of items;>{{item.name}}</li></ul>
<button (click)="getItems()">Get Items</button>
`
})
export class TrackByCmp{
items: any[]=[];
constructor(){
this.items = [{id:'1',name:'Tom'},{id:'2',name:'Jerry'},{id:'3',name:'Kitty'}];
}
getItems(){
this.items = [{id:'1',name:'Tom'},{id:'2',name:'Jerry'},{id:'4',name:'Mac'},{id:'5',name:'John'}];
}
}
複製代碼
有時你會須要改變這個集合,好比從後端接口返回了新的數據。那麼問題來了,Angular 不知道怎麼跟蹤這個集合裏面的項,不知道哪些該添加哪些該修改哪些該刪除。結果就是,Angular 會把該集合裏的項所有移除而後從新添加。就像這樣:
這樣作的弊端是會進行大量的 DOM 操做,而 DOM 操做是很是消耗性能的。
那麼解決方案是,爲*ngFor 添加一個 trackBy 函數,告訴 Angular 該怎麼跟蹤集合的各項。trackBy 函數須要兩個參數,第一個是當前項的 index,第二個是當前項,並返回一個惟一的標識,就像這樣:
import{ Component } from '@angular/core';
@Component({
selector: 'trackBy-test',
template: `
<ul><li *ngFor="let item of items;trackBy: trackByIndex">{{item.name}}</li></ul>
<button (click)="getItems()">Get Items</button>
`
})
export class TrackByCmp{
items: any[]=[];
constructor(){
this.items = [{id:'1',name:'Tom'},{id:'2',name:'Jerry'},{id:'3',name:'Kitty'}];
}
getItems(){
this.items = [{id:'1',name:'Tom'},{id:'2',name:'Jerry'},{id:'4',name:'Mac'},{id:'5',name:'John'}];
}
trackByIndex(index, item){
return index;
}
}
複製代碼
修改以後,Angular 就知道哪些項變更了:
關於 trackBy
的更多講解能夠參考:Angular-使用好NgForOf的trackBy帶來性能上的提高
首先須要在 argular01.component.ts 中定義相關數據內容:
nums: any[] = [111, 222, 333];
flag = false;
order = 1;
複製代碼
html 文件內容以下:
<h3>循環,顯示數據的索引</h3>
<div>
<ul>
<li *ngFor="let item of nums; let key =index">
<span *ngIf="key == 1" class="red">{{key+1}}----{{item}}</span>
<span *ngIf="key != 1">{{key+1}}----{{item}}</span>
</li>
</ul>
</div>
<br>
<h3>判斷</h3>
<div *ngIf="flag">
<p>我是一個P標籤</p>
</div>
<div *ngIf="!flag">
<p>我是一個PP標籤</p>
</div>
<br>
<h3>NgSwitch</h3>
<span [ngSwitch]="order">
<p *ngSwitchCase="1">
1111111111
</p>
<p *ngSwitchCase="2">
2222222222222
</p>
<p *ngSwitchDefault>
00000000000
</p>
</span>
複製代碼
上述內容除了介紹 ngIf 和 ngSwitch 的用法,還提到關於循環索引的定義(索引從0開始),同 ngIf 配合使用。
網頁效果圖以下:
用 ngClass
同時添加或刪除幾個 CSS 類。
<div>
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
<div [class]="isSpecial ? 'special2' : ''">This div is special</div>
</div>
複製代碼
考慮一個 setCurrentClasses()
組件方法,該方法設置一個組件屬性 currentClasses
,該對象具備一個根據其餘三個組件屬性的 true
/ false
狀態來添加或刪除三個 CSS 類的對象。該對象的每一個鍵(key)都是一個 CSS 類名。若是要添加上該類,則其值爲 true
,反之則爲 false
。
home2.component.ts
canSave = true;
isUnchanged = true;
isSpecial = true;
constructor() { }
ngOnInit(): void {
this.setCurrentClasses();
}
setCurrentClasses() {
this.currentClasses = {
'saveable': this.canSave,
'modified': !this.isUnchanged,
'special': this.isSpecial
};
}
複製代碼
CSS 樣式:
.saveable{
background-color: blue;
}
.modified{
font-size: 21px;
}
.special{
font-weight: 200;
}
.special2{
font-weight: 200;
}
複製代碼
頁面測試:
從上述例子能夠看出,當添加單個類時,使用類綁定和 Ngclass 效果是一致的。因此官方文檔推薦: 要添加或刪除單個類,請使用類綁定而不是 NgClass
。
使用 NgStyle
根據組件的狀態同時動態設置多個內聯樣式。
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
This div is x-large or smaller.
</div>
複製代碼
下面的例子是一個 setCurrentStyles()
方法,它基於該組件另外三個屬性的狀態,用一個定義了三個樣式的對象設置了 currentStyles
屬性。
currentStyles: any = {};
canSave = true;
isUnchanged = true;
isSpecial = true;
constructor() { }
ngOnInit(): void {
this.setCurrentStyles();
}
setCurrentStyles() {
// CSS styles: set per current state of component properties
this.currentStyles = {
'font-style': this.canSave ? 'italic' : 'normal',
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
'font-size': this.isSpecial ? '24px' : '12px'
};
}
複製代碼
頁面測試:
同 ngClass 同樣,官方文檔一樣推薦設置單個樣式值採用樣式綁定,設置多個內聯樣式,請使用 NgStyle
指令 。
管道是格式化字符串、金額、日期和其它顯示數據的好辦法
Angular 自帶了不少管道,好比 date 管道和 currency 管道,完整的列表參見 Pipes API 列表。你也能夠本身定義一些新管道。
在 birthday.component.ts
文件中設置以下:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-birthday',
templateUrl: '
<p>The hero's birthday is {{ birthday | date:format }}</p>
<button (click)="toggleFormat()">Toggle Format</button>
'
})
export class BirthdayComponent implements OnInit {
birthday = new Date(1988, 3, 15); // April 15, 1988
toggle = true; // start with true == shortDate
constructor() { }
ngOnInit(): void {
}
get format() { return this.toggle ? 'shortDate' : 'fullDate'; }
toggleFormat() { this.toggle = !this.toggle; }
}
複製代碼
網頁展現效果:
Angular 安全導航運算符 ?
能夠對在屬性路徑中出現 null
和 undefined
值進行保護。在這裏,若是 item
爲 null
,它能夠防止視圖渲染失敗。
<p>The item name is: {{item?.name}}</p>
複製代碼
若是 item
爲 null
,則視圖仍然渲染,但顯示的值爲空白;您只會看到 「The item name is:」 ,後面沒有任何內容。
考慮接下來這個帶有 nullItem
的例子。
The null item name is {{nullItem.name}}
複製代碼
因爲沒有安全導航運算符,而且 nullItem
爲 null
,所以 JavaScript 和 Angular 會引起空指針錯誤並中斷 Angular 的渲染過程:
content_copyTypeError: Cannot read property 'name' of null.
複製代碼
可是,有時在某些狀況下,屬性路徑中的 null
值多是可接受的,尤爲是當該值開始時爲空但數據最終會到達時。
使用安全導航運算符 ?
,當 Angular 表達式遇到第一個空值時,它將中止對錶達式的求值,並渲染出無錯誤的視圖。
數據綁定是一種機制,用來協調用戶可見的內容,特別是應用數據的值。 雖然也能夠手動從 HTML 中推送或拉取這些值,可是若是將這些任務轉交給綁定框架,應用就會更易於編寫、閱讀和維護。 您只需聲明數據源和目標 HTML 元素之間的綁定關係就能夠了,框架會完成其他的工做。
Angular 提供了多種數據綁定方式。綁定類型能夠分爲三類,按數據流的方向分爲:
數據綁定的目標是 DOM 中的對象。 根據綁定類型,該目標能夠是 Property 名(元素、組件或指令的)、事件名(元素、組件或指令的),有時是 Attribute 名。下表中總結了不一樣綁定類型的目標。 關於這一部分會結合例子進行演示,沒有固定篇幅進行講解,詳細內容能夠參考:Angular模塊語法
首先修改 html 文件:
<h3>事件</h3>
<button (click)="run()">執行事件</button>
<br>
<br>
<button (click)="getData()">獲取數據</button>
<br>
<br>
<strong>{{title}}</strong>
<br>
<br>
<button (click)="setData()">設置數據</button>
<br>
<br>
<button (click)="runEvent($event)" id="btn">執行方法獲取事件對象</button>
<br>
複製代碼
而後在 argular01.component.ts 文件中添加實現方法
title = '這是一個主題';
keywords = '這是一個input'
run() {
alert('hello');
}
constructor() { }
ngOnInit(): void {
}
getData() {
alert(this.title);
}
setData() {
this.title = '新的主題';
}
runEvent(e) {
var dom = e.target;
dom.style.color = 'red';
}
複製代碼
網頁展現效果以下:
html 文件:
<h3>表單事件 事件對象</h3>
<!--<input type="text" (keydown)="keydown()">-->
<br>
<input type="text" (keydown)="keydown($event)">
<br>
<input type="text" (keyup)="keyup($event)" >
複製代碼
而後在 argular01.component.ts 文件中添加實現方法
keydown(e) {
console.log(e.target.value);
}
keyup(e) {
if (e.keyCode == 13) {
console.log('敲了一下回車');
}
}
複製代碼
網頁展現效果以下:
補充語句與事件綁定的例子,語句上下文能夠引用模板自身上下文中的屬性,在上面例子中把模板的$event對象傳給了組件中的事件處理方法,還能夠將模板輸入變量 (let key
)和模板引用變量 (#inputDom
) 傳到組件方法中。
<input type="text" #inputDom (input)="getData2(inputDom.value)" />
<br>
<div>
<ul>
<li *ngFor="let item of nums; let key =index">
<span>{{key+1}}----{{item}}</span>
<button (click)="delete(key)">X</button>
</li>
</ul>
</div>
複製代碼
事件方法定義以下:
getData2(data: any) {
console.log(data);
}
delete(key) {
this.nums.splice(key, 1);
}
複製代碼
頁面測試:
雙向綁定會作兩件事:
設置特定的元素屬性。
監聽元素的變動事件。
Angular 爲此提供了一種特殊的雙向數據綁定語法 [()]
。[()]
語法將屬性綁定的括號 []
與事件綁定的括號 ()
組合在一塊兒。
首先在 app.module.ts 裏面引入 NgModule 並聲明。
// 瀏覽器解析的模塊
import { BrowserModule } from '@angular/platform-browser';
// Angular核心模塊
import { NgModule } from '@angular/core';
import {FormsModule} from '@angular/forms';
// 根組件
......
// @NgModule裝飾器,@NgModule接受一個元數據對象,告訴 Angular 如何編譯和啓動應用
@NgModule({
declarations: [// 配置當前項目運行的組件
AppComponent, NewsComponent, Argular01Component, FormComponent, SearchComponent
],
imports: [// 配置當前模塊運行依賴的其餘模塊
BrowserModule,
FormsModule
],
providers: [StorageService],
bootstrap: [AppComponent]
})
export class AppModule { }
複製代碼
html 文件內容:
<h3>雙向綁定</h3>
<p><input type="text" [(ngModel)]="keywords"></p>
<span>{{keywords}}</span>
<br>
<br>
<span><button (click)="upkeywords()">修改數據</button></span>
複製代碼
最後在 argular01.component.ts 定義變量和方法。
keywords = '這是一個input';
upkeywords() {
this.keywords = '改變後的數據';
}
複製代碼
網頁展現效果:
關於 input 框雙向數據綁定,在上面介紹的 (input)="getData2(inputDom.value)"
方法,修改一下也能夠實現一樣的效果。
html 文件:
<p>input數據綁定:<input [value]="keywords"
(input)="keywords=$event.target.value" ></p>
<span>{{keywords}}</span>
複製代碼
上面的代碼在把輸入框的 value
屬性綁定到 name
屬性。 要監聽對值的修改,代碼綁定到輸入框的 input
事件。 當用戶形成更改時,input
事件被觸發,並在包含了 DOM 事件對象 ($event
) 的上下文中執行這條語句。
要更新 name
屬性,就要經過路徑 $event.target.value
來獲取更改後的值。
頁面測試:
新建一個組件:
ng g component components/form
複製代碼
首先在 app.module.ts 裏面引入 NgModule 並聲明。
一、form.component.html
<h2>人員登記系統</h2>
<!--講解表單 input、checkbox、radio、select、textarea實如今線預定功能-->
<div class="people_list">
<ul>
<li>
姓 名:
<input type="text" [(ngModel)]="peopleInfo.username" id="username" class="form_input">
</li>
<li>
性 別:
<input type="radio" value="1" name="sex" id="man" [(ngModel)]="peopleInfo.sex"> <label for="man">男</label>
<input type="radio" value="2" name="sex" id="woman" [(ngModel)]="peopleInfo.sex"> <label for="woman">女</label>
</li>
<li>
城 市:
<select [(ngModel)]="peopleInfo.city">
<option *ngFor="let item of peopleInfo.cities">
{{item}}
</option>
</select>
</li>
<li>
愛 好:
<span *ngFor="let item of peopleInfo.hobbies;let key=index" >
<input type="checkbox" [id]="'check'+key" [(ngModel)]="item.checked"><label [for]="'check'+key">{{item.title}}</label>
</span>
</li>
<li>
備 注:
<textarea [(ngModel)]="peopleInfo.remark" cols="30" rows="2"></textarea>
</li>
<br>
<button (click)="getData()">獲取表單的值</button>
<pre>
{{peopleInfo | json}}
</pre>
</ul>
</div>
複製代碼
二、form.component.css
ul,ol{
list-style-type: none;
}
*{
margin: 0px;
padding:0px;
}
h2{
text-align: center;
}
.people_list{
width: 400px;
margin: 40px auto;
padding: 20px;
border: 1px solid #eeeeee;
}
.people_list li{
height: 50px;
line-height: 50px;
}
.form_input{
width: 300px;
height: 28px;
}
複製代碼
三、form.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent implements OnInit {
peopleInfo: any = {
username: '',
sex: '1',
cities: ['北京', '上海', '深圳'],
city: '上海',
hobbies: [
{
title: '吃飯',
checked: false
},
{
title: '睡覺',
checked: false
},
{
title: '寫代碼',
checked: true
}
],
remark: ''
}
constructor() { }
ngOnInit(): void {
}
getData() {
console.log(this.peopleInfo);
}
}
複製代碼
四、網頁展現效果
五、小結
對於性別單選和愛好多選框,勾選時前臺發生了什麼變化,雙向數據綁定了什麼樣的數據。
上面動圖中注意觀察 ng-reflect-model 值的變化。
新建一個組件:
ng g component components/search
複製代碼
首先在 app.module.ts 裏面引入 NgModule 並聲明。
一、search.component.html
<h2>search</h2>
<div class="search">
<input type="text" [(ngModel)]="keyWord" (keyup)="keyup($event)"> <button (click)="search()">搜索</button>
<hr>
<ul>
<li *ngFor="let item of keyWordsOld;let key=index"> {{item}} ----- <button (click)="delete(key)">X</button></li>
</ul>
</div>
複製代碼
二、search.component.ts
keyWord: any = '';
keyWordsOld: any[] = [];
keyup(e) {
if (e.keyCode === 13){
if (this.keyWordsOld.indexOf(this.keyWord) === -1) {
this.keyWordsOld.push(this.keyWord);
}
this.keyWord = '';
}
}
search() {
if (this.keyWordsOld.indexOf(this.keyWord) == -1) {
this.keyWordsOld.push(this.keyWord);
}
this.keyWord = '';
}
delete(key) {
this.keyWordsOld.splice(key, 1);
}
複製代碼
三、網頁展現效果
結合咱們平常使用淘寶京東的習慣,搜索記錄都會保留下來,這就涉及到數據持久化,後續會整合講解。
練習雙向綁定來實現代辦事項和已完成事項的轉變。
一、search.component.html
<h2>搜 索todoList</h2>
<div class="search">
<input type="text" [(ngModel)]="product" (keyup)="add($event)" >
<hr>
待辦事項
<ul>
<li *ngFor="let item of products;let key=index" [hidden]="item.status == 1">
<input type="checkbox" [(ngModel)]="item.status">{{item.status}} ---- {{item.title}}
----- <button (click)="deleteWay(key)">X</button>
</li>
</ul>
<hr>
已辦事項
<ul>
<li *ngFor="let item of products;let key=index" [hidden]="item.status == 0">
<input type="checkbox" [(ngModel)]="item.status" >{{item.status}} ---- {{item.title}}
----- <button (click)="deleteWay(key)">X</button>
</li>
</ul>
<hr>
<div>
<pre>
{{products | json}}
</pre>
</div>
</div>
複製代碼
二、search.component.ts
product: any = '';
products: any[] = [];
add(e) {
// tslint:disable-next-line:triple-equals
if (e.keyCode == 13) {
if (!this.equalProduct(this.products, this.product)) {
this.products.push({
title: this.product,
status: 0
});
this.product = '';
} else {
alert('數據已存在');
this.product = '';
}
}
}
deleteWay(key) {
this.products.splice(key, 1);
}
equalProduct(products: any[], value: any) {
if (!value || value === '') {
return false;
}
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < products.length; i++) {
// tslint:disable-next-line:triple-equals
if (products[i].title == value) {
return true;
}
}
return false;
}
複製代碼
三、網頁展現效果