angular2 學習筆記 ( 4.0 初探 )

目前是 4.0.0-rc.2. 

剛好有個小專案要開發,就直接拿它來試水啦.

 

更新 cli 到最新版, 建立專案, 然後 follow https://github.com/angular/angular/blob/master/CHANGELOG.md 升級去 4.0

遇到一個 error https://github.com/angular/angular-cli/issues/5131

更新 typescript 就可以了.

 

一些新功能和 break change 

1. template 替換成 ng-template 了

<template #loading>Loading...</template> <!--棄用了-->
<ng-template #loading>Loading...</ng-template> <!--新的用這個-->

2. if else 增強 

<ng-template #loading>Loading...</ng-template> 
<div *ngIf="user$ | async; else loading; let user">
  {{ user.name }}
</div>

我們可以很容易的寫出這種等待 ajax 資料的程式碼. 

let user 獲取到的就是 user$.next 的 value 啦, loading 則是對應一個 ng-template.

RC.5 更新 (一如往常, ng 在 RC 階段依然可以加入新功能和 breaking change. 厲害吧)

ngIf 和 ngFor 微語法新加入了 "as" 這個詞法. 

之前 *ngIf="user$ | async; else loading;let user"
之後 *ngIf="user$ | async as user; else loading"

取代了 let, 好處就是, 語義比較有連貫,比較熟悉.

ngFor 也可以

<!--之前-->
<div *ngFor="let item of ['a','b','c'] as items; let i = index">
  {{item}} {{items.length}} {{i}}
</div>

<!--之後, 使用 as 替代了 let-->
<div *ngFor="let item of ['a','b','c'] as items; index as i">
  {{item}} {{items.length}} {{i}}
</div>

<!--之後, 使用逗號","也可以哦 -->
<div *ngFor="let item of ['a','b','c'] as items, index as i">
  {{item}} {{items.length}} {{i}}
</div>

 

3.  Replace references to TrackByFn to TrackByFunction<any> 

 

4. Validators.email 

this.form = this.fb.group({
  email : ["", Validators.email]
});
let emailCtrl = this.form.get("email");
console.log(emailCtrl.valid); //fail
emailCtrl.setValue("hengkeat87@gmail"); 
console.log(emailCtrl.valid); //ok
emailCtrl.setValue("hengkeat87@gmail.com"); 
console.log(emailCtrl.valid); //ok

這個沒什麼意義, 相信大家早就自己實現了. 應該是做給那些老師方便他們寫 demo 教學生的吧...

 

5. Validators.equalsTo

    this.form = this.fb.group({
       password : ["",Validators.equalsTo("confirmPassword")],
       confirmPassword : [""]
    });

bug : https://github.com/angular/angular/issues/14770

實現原始碼 : https://github.com/angular/angular/commit/7b7ae5f

這個相信大家也自己實現了, 

記得上次自己寫的時候也是遇到 bug /.\ 

 

6. Select option [compareWith]

 <form [formGroup]="form">
    <select [compareWith]="compareModel" formControlName="data" >
      <option *ngFor="let item of items; trackBy:trackBy" [ngValue]="item" >{{ item.text }}</option>
    </select>
 </form>
type Item = { Id: number, value: string, text: string };
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {
  constructor(
    private fb: FormBuilder
  ) { }
  form: FormGroup
  items: Item[]
  trackBy: TrackByFunction<Item> = (index, item) => {
    return item.Id;
  }
  compareModel(a: Item, b: Item) {
    return a.Id === b.Id;
  }
  ngOnInit() {
    this.form = this.fb.group({
      data: [null]
    });
    this.items = [
      { Id: 1, value: "a", text: "A" },
      { Id: 2, value: "b", text: "B" },
      { Id: 3, value: "c", text: "C" }
    ];
    //this.form.get("data").setValue(this.items[0]); // 在沒有 compareWith 的情況下,我們必須放回相同 reference 的物件 
    this.form.get("data").setValue({ Id: 1, value: "a", text: "A" }); //在設定 compareWith 後,我們可以給不同 reference 的物件
  }
}

關鍵就看最後兩行的註釋. 

 

7. router runGuardsAndResolvers

    imports: [RouterModule.forRoot([
        { 
            path: 'home',
            component: HomeComponent
        },
        {
            path : "about",
            component : AboutComponent,
            runGuardsAndResolvers : "always", //"always" || "paramsChange" || "paramsOrQueryParamsChange" 選擇不同的檢測時機
            canActivate : [GuardService]
        },
        {
            path : "",
            redirectTo : "home",
            pathMatch : "full"
        }
    ])],

通過 runGuardsAndResolvers 我們可以設定更多的守衛檢查時機 (2.x版本只有在進入 route 的時候檢查, 如果之後只是修改 params or queryParams 守衛是不會再檢測的),  paramsChange 指的是 matrix. 

 

8. RouteConfigLoadStart | RouteConfigLoadEnd

route 多了2個 event 

當一個 module 被載入 ( preload 也可以) 時就會觸發. 主要用途是讓我們知道 preload module 載入開始和完成了, 2.x 我們沒法監聽到. 

 

9. Renderer 換成 Renderer2 了. 

invokeElementMethod 沒有了, 要怎樣 focus 呢 ? 
listenGlobal 沒有了,  改用 listen("window" | "document" | "body"); 
 

10.

OpaqueToken 沒有了, 改成 InjectionToken<T> 

Injector.get 也有點更換, 支援型別了 

let service = this.injector.get<T>(token: Type<T>|InjectionToken<T>, notFoundValue?: T): T; 

以上的 T 必須是同一個型別哦. 雖然我放不同型別 typescript 也沒有報錯 /.\ 

什麼時候 formControl 才支援型別 . FormControl<T> 不是很好嗎, formContril.value 就有型別可以用 ! 

 

11. 

ngOutletContext 改成 ngTemplateOutletContext

也支援微語法了.

<ng-template #myTemplate let-value="value" >
  <div>{{ value }}</div>
</ng-template>
<ng-template [ngTemplateOutlet]="myTemplate" [ngTemplateOutletContext]="{ value : 'keatkeat' }" ></ng-template>
<div *ngTemplateOutlet="myTemplate; context : { value : 'keatkeat' }"></div> 

 

12. call resolver when upstream params change

2.x 版本的 router resolver 比較笨 

from "/company/1/employer/1" change to "/company/2/employer/1" 

 

children 的 resolve 是不會重跑一次的. 4.0 開始會跑,即使是 parent 的 route 改變了, child 的 resolve 也會重新跑一次. 這才對嘛 

 

13. router CanDeactivate

多了一個 parameter 

@Injectable()
export class BlockOut implements CanDeactivate<HomeComponent> {
    canDeactivate(
        component: HomeComponent,
        currentRoute: ActivatedRouteSnapshot,
        currentstate: RouterStateSnapshot,
        nextState?: RouterStateSnapshot
    ): Observable<boolean> | Promise<boolean> | boolean {
        console.log(currentstate.url); //  /home  
        console.log(nextState.url);    //  /about
        return true;
    }
}

我們依據 next url 來決定要幹什麼. 哎喲, 不錯哦.

 

14. SimpleChanges 多了一個 firstChange 熟悉, 早就該有了嘛!

ngOnChanges(changes: SimpleChanges) {
    let c = changes["value"];
    if (c.firstChange) {
        console.log(c.previousValue); //undefined
        console.log(c.currentValue);  //keatkeat
        console.log(c.isFirstChange()); //true
    }
    else {       
        console.log(c.previousValue); //keatkeat
        console.log(c.currentValue);  //keatkeat2
        console.log(c.isFirstChange()); //false
    } 
}

 

15. MetaService 

和 Title 類似, 就是讓我們可以動態新增修改 Meta 等等. 我還沒有測試 server side render , 4.0 好像也有一些變化. 希望有時間 ^^ 

 

16. NgComponentOutlet

refer : https://github.com/angular/angular/issues/11168

這個功能是不錯,不過我認為 ng 在動態 component 上面還有很多不足夠的地方。 這個連 binding property, event 都沒有,我不打算用, 沒測試了.

 

17 http params 容易寫了

this.http.get("http://localhost:61547/api/businesses",
  {
    params: { time: "2016-01-01T05:15:12.0000000+08:00" }
  }).subscribe(v => console.log(v));

直接傳入物件就可以了. (不過上面這個 time string convert 出來好像怪怪的... /.\)

 

18. Renderer2.setStyle

之前是 setElementStyle, 

setStyle(el: any, style: string, value: any, hasVendorPrefix: boolean, hasImportant: boolean)
hasVendorPrefix 指的是這些 : 
 
19. RequestOptionsArgs.search 換成 .params 
 
20. Pipe 
titlecase, uppercase, lowercase
<h1>{{ title | titlecase }}</h1>

titlecase 是說讓第一個字母大寫, "同時讓後面的字母變小寫", uppercase, lowercase 就不用介紹了吧. 

 

21 ActivatedRoute.paramMap and queryParamMap

其實 param 是可以有多個相同 key 的, 比如 ?data=10&data=11

而獲取的資料是 ActivatedRoute.params["data"] = ["10","11"]; 

ng 為了要更好的區分這個情況而改進了,現在可以使用  ActivatedRoute.paramMap.get("data") or paramMap.getAll("data") 來做single and multiple 區分. 

 

 

 

 

 

 

 
 

 

關鍵詞:item value let 可以 this ng template angular console log

相關推薦:

C基礎 之 list 庫奧義

知識點:Java 集合框架圖

Spring框架入門

day005 java中陣列

Java入門1

【演算法】實現棧和佇列

六、hql語句

js紅寶書總結筆記

.20-淺析webpack原始碼之compile流程-Template模組

JavaScript面向物件輕鬆入門之綜合