angular1.0的這些繁雜的api,還有它的執行速度,運行效率,學習曲線,都被人吐槽,最近一直在用ng1,實在很想吐槽。javascript
最近寫ng2的項目,寫了一些ng2基礎的應用(包括angular-cli,路由,表單驗證,組件通訊,ajax,服務/指令,lazyload)demo,地址在->點我css
學了一下angular2,看它有什麼區別呢?html
我就不復述網上一堆的對比言論了,我僅僅對我項目裏用到的一個點來進行闡述。vue
有個需求就是一個radio對應一個input標籤,好比有兩對。java
我須要選中1的時候傳輸1的value,選中2的時候傳2的vaule。當選中1,2的input必須置空,選中2的時候1能夠有值。還須要拿到數據之後還能顯示回這個頁面。react
ng1作的時候要radio倆ngModel,input倆ngModel,你須要判斷radio是否是被選中。input的ngModel就不用管了。(好的辦法是用事件代理,這樣在傳輸數據沒問題,很簡單,數據回顯的時候就要根據數據推radio的選中狀況了,不操做dom的狀況下還須要加ngModel,不過也是沒辦法的事,否則改交互好了)git
重要的一點是你必須$watch radio對應ngModel,若是沒被選中,那2框置空。。坑的是若是我有好幾個表單,我須要循環表單$watch!!!!坑死了。性能超差。(由於可能在代碼裏修改radio對應的ngModel來手動完成radio的惟一性,否則也不須要watch,事件代理也同樣坑,回顯的時候也必須手動維護一個數組來模擬radio的原生特性,可是能夠避免$watch,由於發送請求數據不須要radio的狀態,因此正在強烈建議重構這個頁面)es6
開始ng2-----------------------------------------------------------------github
ng2一個好的點就是ngModel的轉變,它作的很棒的一點是單項綁定和雙向綁定的選擇,ngModel也是。()是數據到模板的綁定,[ngModel]是模板到數據的綁定。ajax
ng2有Attribute, Class, and Style 綁定,Event Binding。並且都是能夠拼接字符串或者在binding裏面寫表達式,甚至是函數,好比:
ckass(){
return " abc dec"
}
<input type="text" #spy1 [ngClass]="'hahaha'+ckass()" />
想用的心已經蠢蠢欲動了。。
普通的雙向綁定如ng1是這樣寫
<input type="text" [(ngModel)]="input" />
重要的是它能夠拆開:
<input type="checkbox" [ngModel]="input" (ngModelChange)="handleChange()"/> {{ input }}
(ngModelChange)是啥,它裏面能夠隨便寫嗎?
答案是不能。借用雪狼大叔的翻譯:安利一下angular.live
ngModelChange
並非<input>
元素的事件。 它其實是一個來自ngModel
指令的事件屬性。 當Angular在表單中看到一個[(x)]的綁定目標時, 它會期待這個x
指令有一個名爲x
的輸入屬性,和一個名爲xChange
的輸出屬性。
雙向綁定的指令都會有一個xxChange的屬性,它能夠修改綁定。好比咱們給它加個條件,若是radio選中了,就能夠綁定啦, 否則你就是空吧。
<button class="batton" (click)="handleClick($event)"> click me</button> <input type="checkbox" [ngModel]="input" (ngModelChange)="handleChange()"/> <input type="text" [(ngModel)]="input" [disabled]="!check" /> {{ input }}
export class AppComponent { check = false; handleChange(){ this.check = !this.check; if(!this.check) { this.input = ""; } } handleClick(e: any) { this.check = false; } }
這裏留一個button來解決程序修改radio狀態的問題。能夠看到,咱們的handleChange其實就作了一個手動綁定的工做。若是沒選中給置空。
運行你會發現,點擊click me,input的內容並木有置空,由於radio的修改不是模板到數據的過程,是數據到模板的過程。
不要緊,[ngModel]的單項綁定仍然能夠本身控制,好比:
@Component({ selector: 'my-app', template: ` <button class="batton" (click)="handleClick($event)"> click me</button> <input type="checkbox" [ngModel]="handleCheck()" (ngModelChange)="handleChange()"/> <input type="text" [(ngModel)]="input" [disabled]="!check" /> {{ input }} `, styles: [``] })
又來了個handleCheck,這是ng1的ngModel不能搞定的。反正不支持處理函數。
那ng2咋寫:
export class AppComponent { check = false; handleCheck(){ if (!this.check) { this.input = ""; } } handleChange(){ this.check = !this.check; if(!this.check) { this.input = ""; } } handleClick(e: any) { this.check = false; } }
咱們在數據到模板的綁定只須要判斷是否選中就能夠了,這樣就避免了$watch。
還有一些表達方式的不同,主要是由於都換成ts了,一些相似es6的語法都開始發揮做用。
1.模塊注入
由於es6的語法,去掉了ng1的依賴注入,改成模塊化的注入,import語法
import { Component } from '@angular/core';
export class AppModule { }
2.模塊化
因爲ng2的模塊化,本來模塊化不那麼明顯的ng1的語法要改變不少,模塊都做類,新增了註解語法,
@Component({ selector: 'hero', templateUrl: 'component.html' }) export class HeroFormComponent { ... }
Component註解規定了這個模塊的selector,和模板template,而後把這個類作控制器。
3.數據展現
基本相似ng1,雙花括號的展現方式
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>{{title}}</h1> <h2>My favorite hero is: {{myHero}}</h2> ` }) export class AppComponent { title = 'Tour of Heroes'; myHero = 'Windstorm'; }
只是模板選擇器寫在了註解裏,控制器爲此類。
而後這個類就能夠作爲一個模塊使用,其實就是ng1的組件型指令
<my-app>loading...</my-app>
另外,template裏的一些自帶指令也是相似ng1,只是寫法不一樣,除了上面寫的綁定意外,再說一個ngFor
template: ` <h1>{{title}}</h1> <h2>My favorite hero is: {{myHero}}</h2> <p>Heroes:</p> <ul> <li *ngFor="let hero of heroes"> {{ hero }} </li> </ul> `
就是相似ng-repeat的做用了。只是換了個語法,看文檔就行了。
4.dom事件
爲了使鍵盤事件比較方便,而後本身封裝進了ng2,vue已作此工做
<input #box (keyup.enter)="update(box.value)" (blur)="update(box.value)">
其他的事件都是相似的,帶有()括號的單向綁定。
5.服務
服務也有點差距,注入和聲明有點不一樣,此爲聲明
import { Injectable } from '@angular/core';
@Injectable()
export class HeroService {
...
}
當 TypeScript 看到@Injectable()
裝飾器時,就會記下本服務的元數據。 若是 Angular 須要往這個服務中注入其它依賴,就會使用這些元數據。
使用服務首先引入服務
import { HeroService } from './hero.service';
而後須要在註解裏註冊一下
providers: [HeroService]
而後在這個類中就可使用這個服務了
export class AppComponent implements OnInit { title = 'Tour of Heroes'; heroes: Hero[]; constructor(private heroService: HeroService) { } getHeroes(): void { this.heroService.getHeroes().then(heroes => this.heroes = heroes); } ngOnInit(): void { this.getHeroes(); } }
6,生命週期
ng2增長了不少生命週期,如上面的ngOnInit等等,都是ng1沒有的,就不介紹了
7,http
跟ng1相似ng2也是封裝了ajax到http,不一樣的是如今的ng2能夠用rxjs了。。rxjs好像貴族的東西,用的人不多,學習成本不低,可是好用。ng2的http不是封裝的promise了,而是簡化的rx的Observable,須要subscribe來執行他的請求。也能夠引入rx的toPromise,而後then下去就能夠了。有點強破推銷的意思。
8.管道
其實就是ng1的filter。
import { Pipe, PipeTransform } from '@angular/core'; /* * Raise the value exponentially * Takes an exponent argument that defaults to 1. * Usage: * value | exponentialStrength:exponent * Example: * {{ 2 | exponentialStrength:10}} * formats to: 1024 */ @Pipe({name: 'exponentialStrength'}) export class ExponentialStrengthPipe implements PipeTransform { transform(value: number, exponent: string): number { let exp = parseFloat(exponent); return Math.pow(value, isNaN(exp) ? 1 : exp); } }
@Pipe
裝飾器告訴Angular:這是一個管道,管道類實現了PipeTransform
接口的transform
方法,該方法接受一個輸入值和一些可選參數,並返回轉換後的值。transform
方法返回就處理後的值。
9.路由
路由配置沒什麼說的,跟着文檔一步步來就行了,因爲是import的引入,不存在ng1包含路由很大的狀況,根據配置來就行了。這種框架的路由都是相似的。
10. 組件交互
ng1如今都忘記了,主要說一下ng2的組件交互。
父傳子的交互方式是靠props來傳遞的,這點跟react同樣了,子組件的狀態是純靠輸入,這是material的分頁組件,在子組件裏須要用裝飾器來取,@input。下面例子就有
<md-paginator #paginator [length]="xxx" [pageIndex]="0" [pageSize]="10" [pageSizeOptions]="[10]"> </md-paginator>
子傳父組件是不建議的,但也有不少需求,好比打開一個子組件作modal,而後modal關閉的時候回傳給父組件數據,對於react的方案一個是redux,另外一個包括ng1也在用的就是事件系統。都有各自的事件系統,
可是ng2的事件系統最爲強大,由於它是rxjs。
這裏給一個例子:subject就是rxjs的對象。關於rxjs的介紹另有博文:rxjs-流式編程
@Component({ selector: 'wap', template: '<app-add-warp [subject]="subject" ></app-add-warp>' }) export class addWarpComponent { subject = new Subject(); constructor() { this.subject.subscribe({ next: (v) => console.log(v) }); }; }
@Component({ selector: 'app-add', templateUrl: './add.component.html', styleUrls: ['./add.component.scss'] }) export class AddComponent implements OnInit { @Input('subject') cbSubject:Subject<any>; constructor() { } ngOnInit() { this.cbSubject.next(this.user); } } }
subscribe就是觸發事件要執行的東西,next方法就是觸發事件的點。