Angular

一、數據綁定的四種形式:

(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>

  • 綁定到特定類名    單個class的添加與移除

   <div [class.special]='isTrue'></div>

           同時添加或移除多個class

     <div [ngClass]="{'background':isBg,'fontColor':isFontColor}"></div>

樣式綁定

  • 單個樣式綁定   <button [style.color]="isSpecial?'red':'green'"></button>

二、指令

(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>來解決

 

2.三、<ng-container> VS<ng-template> VS <ng-content>

<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,加載對應的模塊代碼塊,不過更強大,像是調用一個函數,能夠傳參

在使用 *ngTemplateOutlet 的時候,能夠加上 context 表明要傳入 ng-template 的參數,好比

<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把組件與服務區分開,以提升模塊性和複用性。經過把組件中和視圖相關的功能與其餘類型的處理分離開,可使組件類更精簡、高效。

組件應該把諸如從服務器獲取數據、驗證用戶輸入等工做委託給服務。

依賴注入:是組件引入外部構建(如服務)的一種機制。

相關文章
相關標籤/搜索