(1)插值 <p>{{title}}</p>html
(2)屬性綁定 <img [src]="userUrl"/>es6
(3)事件綁定 <button (click)='onSave()'>點擊</button>json
(4)雙向綁定 <input [(ngModel)]='title'/>服務器
在雙向綁定中,數據屬性值經過屬性綁定從組件流到輸入框,當修改輸入框內容時經過事件綁定流回組件,把屬性值設爲最新值。網絡
選擇屬性綁定仍是插值?app
當渲染的數據類型是字符串時,傾向於可讀性更好的插值;可是當數據類型不是字符串時,必須用屬性綁定了。dom
屬性綁定與attribute綁定的區別?curl
用屬性綁定來設置元素的屬性老是好於用字符串設置attribute,可是當元素沒有屬性可綁時,就必須用attribute綁定。函數
如: colspan不是td的屬性佈局
<tr><td [attr.colspan]="1+1">One-Two</td></tr>
CSS類綁定
<div class='bad curly special' [class]='isTrue'></div>
<div [class.special]='isTrue'></div>
同時添加或移除多個class
<div [ngClass]="{'background':isBg,'fontColor':isFontColor}"></div>
樣式綁定
(1)結構型指令:經過添加、移除或替換DOM來修改佈局。如 *ngIf、*ngFor
(2)屬性型指令:會修改現有元素的外觀或行爲。 如 NgClass、NgStyle、NgModel
2.一、爲何要給結構型指令加上「*」?
星號是用來簡化更復雜語法的「語法糖」,從內部實現來講,Angular把*ngIf屬性翻譯成了一個<ng-template>元素,並用它來包裹宿主元素
如<div *ngIf="hero">hero</div> =======》
<ng-template [ngIf]="hero">
<div>hero</div>
</ng-template>
2.二、*ngIf有else
<div *ngIf="display else noData"></div> <ng-template #noData></ng-template>
在Angular中一個標籤上不能同時使用兩個指令,能夠經過在外層添加一個<ng-container>來解決
<ng-container>渲染所包含的模板內容,不包含自身
<div> <ng-container> <span>Hello World!</span> </ng-container> </div> <!-- 實際渲染結果是 --> <div> <span>Hello World!</span> </div>
<ng-template>它不會直接渲染任何內容,主要是配合其餘的結構型指令一塊兒使用
<ng-template> <span>Hello World!</span> </ng-template> <!-- 默認不會渲染任何內容 -->
<ng-content>使得這個組件能接收外部投射進來的內容,也就是說組件最終呈現的內容不只僅是自己定義的那些。
父組件在調用子組件時,還能夠在子組件裏添加內容,而後在子組件中使用<ng-content>顯示那部份內容到該處。
//父組件中調用子組件 app-with-title <app-with-title> <div>hello</div> <div>world</div> </app-with-title> //子組件 <div>title</div> <ng-content></ng-content> // 子組件實際渲染的結果是 <div>title</div> <div>hello</div> <div>world</div>
2.四、ng-container 只會展現包含的內容
下面的實例,很好的展現了 ng-container 的用法;需求是隻展現奇數的數據,若是是同時使用 ngFor 和 ngIf 會報錯
<ul> <li *ngFor="let item of list; let odd = odd" * ngIf="odd"> {{ item }} </li> </ul>
<ul> <ng-container *ngFor="let item of list; let odd = odd"> <li *ngIf="odd">{{ item }}</li> </ng-container> </ul>
2.五、*ngTemplateOutlet
<ng-template #data> Hello World </ng-template> <div *ngTemplateOutlet="data"></div>
相似 angularJS 裏面的 include,加載對應的模塊代碼塊,不過更強大,像是調用一個函數,能夠傳參
在使用 *
<div *ngTemplateOutlet="data; context: {$implicit: {value: 1}}"></div> //這個 $implicit 是一個固定用法,就像es6 module中的export default同樣, $implicit 後面的值,會被當作傳入 ng-template 的默認參數 //在 ng-template 裏只須要使用 let-xxx 的方式,就能夠接收到這個傳入的默認參數 <ng-template #data let-xxx> {{ xxx | json }} </ng-template> <div *ngTemplateOutlet="data; context: {$implicit: {value: 1}}"></div> //使用 let-xxx,ng-template 內部就有一個 xxx 變量,這裏 xxx 的值就是 {value : 1}
ng-template 傳入多個參數
$implicit 的方式實際上就是 let-xxx="$implicit",若是有多個參數須要傳入,能夠這樣:
<ng-template #data let-xxx let-another="another"> <div>{{ xxx | json }}</div> <div>{{ another | json }}</div> </ng-template> <div *ngTemplateOutlet="data; context: {$implicit: {value: 1}, another: {value: 2}}" ></div>
使用Angular的模板引用變量,這些變量提供了從模板中直接訪問元素的能力,在標識符前加上井號# 就能直接聲明一個模板引用變量了。
<input #box/> <p>{{box.value}}</p>
//按鍵事件過濾
<input #box (keyup.enter)="onEnter(box.value)"/>
onkey(value:string){
this.value=value;
}
經過$event對象取得用戶輸入
<input (keyup)="onkey($event)"/> onkey(event:any){ this.value=event.target.value; }
可是經過$event是靠不住的作法,反對把整個dom事件傳入方法中,由於這樣組件會知道太多模板的信息,這樣就違反了模板和組件之間的分離關注原則了。
(1)父---->子
子組件若接收來自父組件傳入的消息,必須定義一個輸入屬性,該屬性經過Input裝飾器修飾的。
//子組件 child.ts @Input() private message:string; //父組件 html <child [message]="msgToChild"></child>
(2)子----->父
經過輸出接口完成
//子組件 child.ts @Output() private outer=new EventEmitter<string>(); sendToParent(){ this.outer.emit('message from child'); } //父組件 //. html <child (outer)="recieve($event)"></child> //.ts private msgFromChild:string; recieve($e:any){ this.msgFromChild=$e; }
(3)父子組件經過本地變量互動
父組件不能使用數據綁定來讀取子組件的屬性或調用子組件的方法,可是,能夠在父組件的模板中,新建一個本地變量來表明子組件,而後利用這個變量來讀取子組件的屬性和調用子組件的方法。
//html文件
<child #children></child> //子組件 <button (click)="children.start()"></button>
(4)@viewChild()
兩種用法:一、讀取子組件
若是父組件的類須要讀取子組件的值或方法,就不能使用本地變量的方法了。當父組件須要這種訪問時,能夠把子組件做爲viewChild注入到父組件中
//html文件 <child></child> //子組件 <button (click)="start()"></button> //ts文件 import { child} from './components/child.component'; @viewChild(child); private sonComponent:child; start(){ this. sonComponent.start(); }
@viewChild()的另外一種用法:二、獲取當前組件視圖的單個元素
//.html <input #name/> //.ts @viewChild('name') myName:ElementRef; this.myName.nativeElement.focus();
<router-outlet></router-outlet>把要顯示在這個出口處的組件顯示在這裏。
路由跳轉
<a routerLink="/heroes" routerLinkActive="active">Heroes</a> <a routerLink="['/heroes']">Heroes</a> <a routerLink="[/home]"+row.id>Heroes</a>//根據id跳轉 //routerLinkActive表示當連接激活時添加「active」類 this.router.navigate(['/home']); 在ts文件中
根據參數跳轉路由:
{ path:'home/:id', component:HomeComponent } //獲取參數id //(1) constructor(private route:ActivatedRoute){ route.params.subscribe(params=>{this.id=params['id']}) } //(2) constructor(private route:ActivatedRoute){} const id=this.route.snapshot.paramMap.get('id');
把數據做爲輸入,而後轉換它,給出指望的輸出。
<p>Hero`s birthdat is {{birthday | date}}</p>
讓組件的birthday值經過管道操做符(|)流動到右側的date管道函數中,全部管道都會用這種方式工做。
爲何要用服務?
一般須要對訪問的數據作後處理、添加錯誤處理器,還可能加一些重試邏輯,以便應對網絡問題。若是直接寫在組件中,會由於這些數據方式的細節而變得雜亂不堪,組件變得難以理解,難以測試,而且這些數據訪問邏輯沒法被複用,也沒法標準化,因此把數據展現邏輯與數據訪問邏輯分開。
Angular把組件與服務區分開,以提升模塊性和複用性。經過把組件中和視圖相關的功能與其餘類型的處理分離開,可使組件類更精簡、高效。
組件應該把諸如從服務器獲取數據、驗證用戶輸入等工做委託給服務。
依賴注入:是組件引入外部構建(如服務)的一種機制。