關於angular1與angular2的應用區別

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方法就是觸發事件的點。

相關文章
相關標籤/搜索