Angular 從0到1(九):查缺補漏大合集(下)

第一節(jié):初識Angular-CLI
第二節(jié):登錄組件的構(gòu)建
第三節(jié):建立一個待辦事項應(yīng)用
第四節(jié):進化恐疲!模塊化你的應(yīng)用
第五節(jié):多用戶版本的待辦事項應(yīng)用
第六節(jié):使用第三方樣式庫及模塊優(yōu)化用
第七節(jié):給組件帶來活力
Rx--隱藏在Angular 2.x中利劍
Redux你的Angular 2應(yīng)用
第八節(jié):查缺補漏大合集(上)
第九節(jié):查缺補漏大合集(下)

第九章:查缺補漏大合集(下)

Angular2 動畫再體驗

State和Transition

我寫文章的習(xí)慣是先試驗再理論,所以我們接下來梳理下Angular2提供的動畫技能套么。還是從最簡單的例子開始培己,一個非常簡單的模版:

<div class="traffic-light"></div>

同樣非常簡單的樣式(其實就是畫一個小黑塊):

.traffic-light{  
  width: 100px;  
  height: 100px;  
  background-color: black;
}

現(xiàn)在的效果就是這個樣子,如圖所示胚泌,一點都不酷啊漱凝,沒關(guān)系,我們一點點來诸迟,越簡單的越容易弄懂概念。

一點也不酷的小黑塊
一點也不酷的小黑塊

下面我們?yōu)榻M件添加一個animations的元數(shù)據(jù)描述:

import { 
  Component, 
  trigger,
  state,
  style
} from '@angular/core';

@Component({
  selector: 'app-playground',
  templateUrl: './playground.component.html',
  styleUrls: ['./playground.component.css'],
  animations: [
    trigger('signal', [
      state('go', style({
        'background-color': 'green' 
      }))
    ])
  ]
})
export class PlaygroundComponent {
  
  constructor() { }

}

我們注意到animations中接受的是一個數(shù)組愕乎,這個數(shù)組里面我們使用了一個叫trigger的函數(shù)阵苇,trigger接受的第一個參數(shù)是觸發(fā)器的名字,第二個參數(shù)是一個數(shù)組感论。這個數(shù)組是由一種叫state的函數(shù)和叫transition的函數(shù)組成的绅项。

那么什么是state?state表示一種狀態(tài)比肄,當(dāng)這種狀態(tài)激活時快耿,state所附帶的樣式就會附著在應(yīng)用trigger的那個控件上囊陡。transition又是什么呢?tranistion描述了一系列動畫的步驟掀亥,在狀態(tài)遷移時這些動畫步驟就會執(zhí)行撞反。
我們現(xiàn)在的這個版本中暫時只有state而沒有transition,讓我們先來看看效果搪花,當(dāng)然在可以看到效果前我們先要把這個trigger應(yīng)用到某個控件上遏片。那在我們的例子里就是模版中的那個div了。

<div
    [@signal]="'go'"
    class="traffic-light">
</div>

返回瀏覽器撮竿,你會發(fā)現(xiàn)那個小黑塊變成小綠塊了吮便,如圖所示

小黑塊變成小綠塊

這說明什么?我們的state的樣式附著在div上了幢踏。為什么呢髓需?因為 [@signal]="'go'" 定義了trigger的狀態(tài)是go。但這一點也不酷是嗎房蝉?是的僚匆,暫時是這樣,還是那句話惨驶,不要急白热。
接下來,我們再加一個狀態(tài) stop粗卜,在stop激活時我們要把小方塊的背景色設(shè)為紅色屋确,那么我們需要把animations改成下面的樣子:

animations: [
    trigger('signal', [
      state('go', style({
        'background-color': 'green' 
      })),
      state('stop', style({
          'background-color':'red'
      }))
    ])
  ]

同時我們需要給模板加兩個按鈕Go和Stop。現(xiàn)在的模版看起來是下面的樣子

<div
  [@signal]="signal"
  class="traffic-light">
</div>
<button (click)="onGo()">Go</button>
<button (click)="onStop()">Stop</button>

當(dāng)然你看得到续扔,我們點擊按鈕時需要處理對應(yīng)的點擊事件攻臀。在這里我們希望點擊Go時,方塊變綠纱昧,點擊Stop時方塊變紅刨啸。如果要達成這個目的,我們需要一個叫signal的成員變量识脆,在點擊的處理函數(shù)中更改相應(yīng)的狀態(tài)设联。

export class PlaygroundComponent {

  signal: string;

  constructor() { }

  onGo(){
    this.signal = 'go';
  }
  onStop(){
    this.signal = 'stop';
  }
}

現(xiàn)在打開瀏覽器,試驗一下灼捂,我們會發(fā)現(xiàn)點擊Go變綠离例,而點擊Stop變紅。但是還是沒動起來啊悉稠,是的宫蛆,這是因為我們還沒加transition呢,我們只需把animations改寫一下的猛,你分別點Go和Stop就能看到動畫效果了耀盗。為了讓效果更明顯一些想虎,我們?yōu)閮煞N狀態(tài)指定一下高度。

import { 
  Component, 
  OnDestroy,
  trigger,
  state,
  style,
  transition,
  animate
} from '@angular/core';

@Component({
  selector: 'app-playground',
  templateUrl: './playground.component.html',
  styleUrls: ['./playground.component.css'],
  animations: [
    trigger('signal', [
      state('void', style({
        'transform':'translateY(-100%)'
      })),
      state('go', style({
        'background-color': 'green', 
        'height':'100px'
      })),
      state('stop', style({
          'background-color':'red',
          'height':'50px'
      })),
      transition('void => *', animate(5000))
    ])
  ]
})
export class PlaygroundComponent {
  
  signal: string;

  constructor() { }

  onGo(){
    this.signal = 'go';
  }
  onStop(){
    this.signal = 'stop';
  }
}

那么 transition('* => *', animate(500)) 這句什么意思呢叛拷?前面那個 '* => *' 是一個狀態(tài)遷移表達式舌厨,* 表示任意狀態(tài),所以這個表達式告訴我們胡诗,只要有狀態(tài)的變化就會激發(fā)后面的動畫效果邓线。后面的就是告訴Angular做500毫秒的動畫,這個動畫默認是從一個狀態(tài)過渡到另一個狀態(tài)』突郑現(xiàn)在大家打開瀏覽器體驗一下骇陈,分別點擊Go和Stop,會發(fā)現(xiàn)我們的小方塊從一個正方形變成一個長方形瑰抵,紅色變成綠色的過程你雌。體驗完之后再來看這句話:動畫其實就是由若干個狀態(tài)組成,由transition定義狀態(tài)過渡的步驟二汛。

有了形狀和顏色變化的動畫

那么下面我們介紹一個void 狀態(tài)(空狀態(tài))婿崭,為什么會有void狀態(tài)呢?其實剛剛我們也體驗了肴颊,只不過沒有定義這個void 狀態(tài)而已氓栈。我們在組件中并沒有給signal賦初始值,這就意味著一開始trigger的狀態(tài)就是void婿着。我們往往在實現(xiàn)進場或離場動畫時需要這個void狀態(tài)授瘦。void狀態(tài)就是描述沒有狀態(tài)值時的狀態(tài)。

animations: [
    trigger('signal', [
      state('void', style({
        'transform':'translateY(-100%)'
      })),
      state('go', style({
        'background-color': 'green', 
        'height':'100px'
      })),
      state('stop', style({
          'background-color':'red',
          'height':'50px'
      })),
      transition('* => *', animate(500))
    ])
  ]

上面代碼定義了一個void狀態(tài)竟宋,而且樣式上有一個按Y軸做的-100%的位移提完,其實這就是一開始讓小方塊從場景外進入場景內(nèi),這樣就是實現(xiàn)了一種進場動畫丘侠,大家可以在瀏覽器中試驗一下徒欣。

用void狀態(tài)實現(xiàn)的進場動畫

奇妙的animate函數(shù)

上面的我們的實驗中,你會發(fā)現(xiàn)transition中有個animate函數(shù)蜗字,可能你認為它就是指定一個動畫的時間的函數(shù)打肝。它的身手可不止那么簡單呢,我們來仔細挖掘一下挪捕。
首先呢闯睹,我們來對上面的代碼做一個小改造,把animations數(shù)組改成下面的樣子:

animations: [
    trigger('signal', [
      state('void', style({
        'transform':'translateY(-100%)'
      })),
      state('go', style({
        'background-color': 'green', 
        'height':'100px'
      })),
      state('stop', style({
          'background-color':'red',
          'height':'50px'
      })),
      transition('* => *', animate('.5s 1s'))
    ])
  ]

我們其實只對animate中的參數(shù)做了一點小改動担神,就是把animate(500) 改成animate('.5s 1s')。那么.5s表示動畫過渡時間為0.5秒(其實和上面設(shè)置的500毫秒是一樣的)始花,1s表示動畫延遲1秒后播放⊥叮現(xiàn)在我們打開瀏覽器孩锡,看看效果如何吧。

當(dāng)然還有更狠的大招亥贸,這個字符串表達式還可以變成 '.5s 1s ease-out'躬窜,后面的這個ease-out是一種緩動函數(shù),它是可以讓動畫效果更真實的一種方式炕置。
現(xiàn)實世界中物體照著一定節(jié)奏移動荣挨,并不是一開始就移動很快的,也不可能是一直勻速運動的朴摊。怎么理解呢默垄?當(dāng)皮球往下掉時,首先是越掉越快甚纲,撞到地上后回彈口锭,最終才又碰觸地板。而緩動函數(shù)可以使動畫的過渡效果按照這樣的真實場景抽象出的對應(yīng)函數(shù)來進行繪制介杆。ease-out只是眾多的緩動函數(shù)的其中一種鹃操,我們當(dāng)然可以指定其他函數(shù)。
另外需要說明的一點是諸如ease-out只是真實函數(shù)的一個友好名稱春哨,我們當(dāng)然可以直接指定背后的函數(shù):cubic-bezier(0, 0, 0.58, 1) 荆隘。我們下個小例子不用這個ease-out,因為效果可能不是特別明顯赴背,我們找一個明顯的椰拒,使用 cubic-bezier(0.175, 0.885, 0.32, 1.275) 。現(xiàn)在我們打開瀏覽器癞尚,你仔細觀察一下是否看到了小方塊回彈的效果

animations: [
    trigger('signal', [
      state('void', style({
        'transform':'translateY(-100%)'
      })),
      state('go', style({
        'background-color': 'green', 
        'height':'100px'
      })),
      state('stop', style({
          'background-color':'red',
          'height':'50px'
      })),
      transition('* => *', animate('.5s 1s cubic-bezier(0.175, 0.885, 0.32, 1.275)'))
    ])
  ]

加上了緩動函數(shù)的進場動畫

關(guān)于緩動函數(shù)的更多資料可以訪問 http://easings.net/zh-cn 在這里可以看到各種函數(shù)的曲線和效果耸三,以及cubic-bezier函數(shù)的各種參數(shù)

easing.net上列出了各種緩動函數(shù)的曲線和效果
easing.net上列出了各種緩動函數(shù)的曲線和效果

需要注意的一點是Angular2實現(xiàn)動畫的機制其實是基于W3C的Web Animation標(biāo)準(zhǔn),這個標(biāo)準(zhǔn)暫時無法支持所有的cubic-bezier函數(shù)浇揩,只有部分函數(shù)被支持仪壮。這樣的話我們?nèi)绻獙崿F(xiàn)某些不被支持的函數(shù)怎么辦呢?那就得有請我們的關(guān)鍵幀出場了胳徽。

關(guān)鍵幀

何謂關(guān)鍵幀积锅?首先需要知道什么是幀?百度百科給了定義:
幀——就是動畫中最小單位的單幅影像畫面养盗,相當(dāng)于電影膠片上的每一格鏡頭缚陷。在動畫軟件的時間軸上幀表現(xiàn)為一格或一個標(biāo)記。
關(guān)鍵幀——相當(dāng)于二維動畫中的原畫往核。指角色或者物體運動或變化中的關(guān)鍵動作所處的那一幀箫爷。關(guān)鍵幀與關(guān)鍵幀之間的動畫可以由軟件來創(chuàng)建,叫做過渡幀或者中間幀。
先來做一個小實驗虎锚,我們把入場動畫改造成關(guān)鍵幀形式野揪。

import { 
  Component, 
  OnDestroy,
  trigger,
  state,
  style,
  transition,
  animate,
  keyframes
} from '@angular/core';

@Component({
  selector: 'app-playground',
  templateUrl: './playground.component.html',
  styleUrls: ['./playground.component.css'],
  animations: [
    trigger('signal', [
      state('void', style({
        'transform':'translateY(-100%)'
      })),
      state('go', style({
        'background-color': 'green', 
        'height':'100px'
      })),
      state('stop', style({
          'background-color':'red',
          'height':'50px'
      })),
      transition('void => *', animate(5000, keyframes([
        style({'transform': 'scale(0)'}),
        style({'transform': 'scale(0.1)'}),
        style({'transform': 'scale(0.5)'}),
        style({'transform': 'scale(0.9)'}),
        style({'transform': 'scale(0.95)'}),
        style({'transform': 'scale(1)'})
      ]))),
      transition('* => *', animate('.5s 1s cubic-bezier(0.175, 0.885, 0.32, 1.275)'))
    ])
  ]
})
export class PlaygroundComponent {
  // clock = Observable.interval(1000).do(_=>console.log('observable created'));
  signal: string;

  constructor() { }

  onGo(){
    this.signal = 'go';
  }
  onStop(){
    this.signal = 'stop';
  }
}

保存后返回瀏覽器吮成,你應(yīng)該可以看到一個正方形由小變大的進場動畫。

關(guān)鍵幀實現(xiàn)的入場動畫

現(xiàn)在我們來分析一下代碼,這個入場動畫是5秒的時間珍语,我們給出6個關(guān)鍵幀御吞,也就是0s席怪,1s畜普,2s,3s护侮,4s和5s這幾個敌完。對于每個關(guān)鍵幀,我們給出的樣式都是放縮概行,而放縮的比例逐漸加大蠢挡,而且是先快后慢,也就是說我們可以模擬出緩動函數(shù)的效果凳忙。

如果我們不光做放縮业踏,而且在style中還指定位置的話,這個動畫就會出現(xiàn)邊移動邊變大的效果了涧卵。把入場動畫改成下面的樣子試試看吧勤家。

transition('void => *', animate(5000, keyframes([
        style({'transform': 'scale(0)', 'padding': '0px'}),
        style({'transform': 'scale(0.1)', 'padding': '50px'}),
        style({'transform': 'scale(0.5)', 'padding': '100px'}),
        style({'transform': 'scale(0.9)', 'padding': '120px'}),
        style({'transform': 'scale(0.95)', 'padding': '135px'}),
        style({'transform': 'scale(1)', 'padding': '140px'})
]))),
加上位移的效果

最后的結(jié)果可能還是不酷,但是這樣的話利用關(guān)鍵幀我們?nèi)绻Y(jié)合好CSS樣式柳恐,就會做出比較復(fù)雜的動畫了伐脖。

方便的管道--PIPE

我們一直沒有提到的一點就是管道,雖然我們的例子中沒有用到乐设,但其實這是Angular 2中提供非常方便的一個特性讼庇。這個特性可以讓我們很快的將數(shù)據(jù)在界面上以我們想要的格式輸出出來。還是拿例子說話近尚,比如我們在頁面上顯示一個日期蠕啄,先建立一個簡單的模版:

<p> Without Pipe: Today is {{ birthday }} </p>
<p> With Pipe: Today is {{ birthday | date:"MM/dd/yy" }} </p>

再來建立對應(yīng)的組件文件:

import { Component, OnDestroy } from '@angular/core';

@Component({
  selector: 'app-playground',
  templateUrl: './playground.component.html',
  styleUrls: ['./playground.component.css']
})
export class PlaygroundComponent {
  birthday = new Date();
  constructor() { }

}
無管道和有管道的日期輸出
無管道和有管道的日期輸出

上面的例子可能還沒太明顯,我們 進一步改造一下模板:

<p> Without Pipe: Today is {{ birthday }} </p>
<p> With Pipe: Today is {{ birthday | date:"MM/dd/yy" }} </p>
<p>The time is {{ birthday | date:'shortTime' }}</p>
<p>The time is {{ birthday | date:'medium' }}</p>

同一數(shù)據(jù)可以顯示成不同樣子
同一數(shù)據(jù)可以顯示成不同樣子

而且更牛的是多個Pipes可以串起來使用戈锻,比如說上圖中最下面那個日期我們希望把Dec大寫歼跟,就可以這樣使用:

<p>The time is {{ birthday | date:'medium' | uppercase }}</p>
多個Pipe連用
多個Pipe連用

自定義一個Pipe

那么自己寫一個Pipe是怎樣的體驗?zāi)兀縿?chuàng)建一個Pipe非常簡單格遭,我們來體會一下哈街。首先創(chuàng)建一個 src/app/playground/trim-space.pipe.ts 的文件:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'trimSpace'
})
export class TrimSpacePipe implements PipeTransform {
  transform(value: any, args: any[]): any {
    return value.replace(/ /g, '');
  }
}

在Module文件中聲明這個Pipe:declarations: [PlaygroundComponent, TrimSpacePipe] 以便于其他控件可以使用這個Pipe:

import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { PlaygroundRoutingModule } from './playground-routing.module';
import { PlaygroundComponent }   from './playground.component';
import { PlaygroundService } from './playground.service';
import { TrimSpacePipe } from './trim-space.pipe';

@NgModule({
    imports: [
        SharedModule,
        PlaygroundRoutingModule
    ],
    providers:[
        PlaygroundService
    ],
    declarations: [PlaygroundComponent, TrimSpacePipe]
})
export class PlaygroundModule { }

然后在組件的模板文件中使用即可 {{ birthday | date:'medium' | trimSpace}}

<p> Without Pipe: Today is {{ birthday }} </p>
<p> With Pipe: Today is {{ birthday | date:"MM/dd/yy" }} </p>
<p>The time is {{ birthday | date:'shortTime' }}</p>
<p>The time is {{ birthday | date:'medium' | trimSpace}} with trim space pipe applied</p>
<p>The time is {{ birthday | date:'medium' | uppercase }}</p>

打開瀏覽器看一下效果,我們看到應(yīng)用了trimSpace管道的日期的空格被移除了拒迅,如圖所示:

自定義一個移除空格的Pipe
自定義一個移除空格的Pipe

內(nèi)建的Pipe

Decimal Pipe

DatePipe和UpperCase Pipe我們剛剛已經(jīng)見識過了骚秦,現(xiàn)在我們看一看內(nèi)建的其他Pipe她倘。首先是用于數(shù)字格式化的DecimalPipe。DecimalPipe的參數(shù)是以 {minIntegerDigits}.{minFractionDigits}-{maxFractionDigits} 的表達式形式體現(xiàn)的作箍。其中:

  1. minIntegerDigits 是最小的整數(shù)位數(shù)帝牡,默認是1。
  2. minFractionDigits 表示最小的小數(shù)位數(shù)蒙揣,默認是0。
  3. maxFractionDigits 表示最大的小數(shù)位數(shù)开瞭,默認是3懒震。
<p>pi (no formatting): {{pi}}</p>
<p>pi (.5-5): {{pi | number:'.5-5'}}</p>
<p>pi (2.10-10): {{pi | number:'2.10-10'}}</p>
<p>pi (.3-3): {{pi | number:'.3-3'}}</p>

如果我們在組件中定義 pi: number = 3.1415927; 的話,上面的數(shù)字會被格式化成下圖的樣子

Decimal Pipe用于數(shù)字的格式化
Decimal Pipe用于數(shù)字的格式化

Currency Pipe

顧名思義嗤详,這個Pipe是格式化貨幣的个扰,這個Pipe的表達式形式是這樣的: currency[:currencyCode[:symbolDisplay[:digitInfo]]],也就是說在currency管道后用分號分隔不同的屬性設(shè)置:

<p>A in USD: {{a | currency:'USD':true}}</p>
<p>B in CNY: {{b | currency:'CNY':false:'4.2-2'}}</p>

上面的代碼中 USDCNY 表面貨幣代碼葱色,truefalse 表明是否使用該貨幣的默認符號递宅,后面如果再有一個表達式就是規(guī)定貨幣的位數(shù)限制。這個限制的具體規(guī)則和上面Decimal Pipe的類似苍狰,如下圖所示办龄。

Currecy Pipe用于格式化貨幣
Currecy Pipe用于格式化貨幣

Percent Pipe

這個管道當(dāng)然就是用來格式化百分?jǐn)?shù)的,百分?jǐn)?shù)的整數(shù)位和小數(shù)位的規(guī)則也和上面提到的Decimal Pipe和Currency Pipe一致淋昭。如果在組件中定義 myNum: number = 0.1415927; 下面的代碼會輸出成下圖的樣子:

<p>myNum : {{myNum | percent}}</p>
<p>myNum (3.2-2) : {{myNum | percent:'3.2-2'}}</p>

Percent Pipe用來格式化百分?jǐn)?shù)
Percent Pipe用來格式化百分?jǐn)?shù)

Json Pipe

這個管道個人感覺更適合在調(diào)試中使用俐填,它可以把任何對象格式化成JSON格式輸出。如果我們在組件中定義了一個對象:

object: Object = {
  foo: 'bar', 
  baz: 'qux', 
  nested: {
    xyz: 3, 
    numbers: [1, 2, 3, 4, 5]
  }
}; 

那么下面的模板會輸出下圖的樣子翔忽,在調(diào)試階段英融,這個特性很好幫助你輸出可讀性很強的對象格式。當(dāng)然如果你使用了現(xiàn)代化的IDE歇式,這么使用的意義就不是很大了:

<div>
  <p>Without JSON pipe:</p>
  <pre>{{object}}</pre>
  <p>With JSON pipe:</p>
  <pre>{{object | json}}</pre>
</div>

Json Pipe用于以Json形式格式化對象
Json Pipe用于以Json形式格式化對象

指令——Directive

另一個我們一直沒有提到的重要概念就是指令了驶悟,但這個雖然我們沒提到,卻已經(jīng)用過了材失。比如 *ngFor 痕鳍,*ngIf 等,這些都叫做結(jié)構(gòu)性指令豺憔,而像 *ngModel 等屬于屬性型指令额获。
Angular 2中的指令分成三種:結(jié)構(gòu)型(Structural)指令和屬性型(Attribute)指令,還有一種是什么呢恭应?就是Component抄邀,組件本身就是一個帶模板的指令。
結(jié)構(gòu)型指令可以通過添加昼榛、刪除DOM元素來更改DOM樹的布局境肾,比如我們前面使用 *ngFor在todo-list的模板中添加了多個todo-item剔难。而屬性型指令可以改變一個DOM元素的外觀或行為,比如我們利用 *ngModel 進行雙向綁定奥喻,改變了該組件的默認行為(我們在組件中改變某個變量值偶宫,這種改變會直接反應(yīng)到組件上,這并不是組件自身定義的行為环鲤,而是我們通過 *ngModel 來改變的)纯趋。
Angular 2中給出的內(nèi)建結(jié)構(gòu)型指令如下表所示:

名稱 用法 說明
ngIf <div*ngIf="canShow"> 基于canShow表達式的值移除或重新創(chuàng)建部分DOM樹。
ngFor <li *ngFor="let todo of todos"> 把li元素及其內(nèi)容轉(zhuǎn)化成一個模板冷离,并用它來為列表中的每個條目初始化視圖吵冒。
ngSwitch, ngSwitchCase, ngSwitchDefault <div [ngSwitch]="someCondition"></div> 基于someCondition的當(dāng)前值,從內(nèi)嵌模板中選取一個西剥,有條件的切換div的內(nèi)容痹栖。

自定義一個指令也很簡單,我們動手做一個瞭空。這個指令非常簡單就是使任何控件加上這個指令后揪阿,其點擊動作都會在console中輸出 “I am clicked”。由于我們要監(jiān)視其宿主的click事件咆畏,所以我們引入了 HostListener南捂,在onClick方法上用 @HostListen(‘click’) ,表明在檢測到宿主發(fā)生click事件時調(diào)用這個方法鳖眼。

import {
  Directive,
  HostListener
} from '@angular/core';

@Directive({
    selector: "[log-on-click]",
})
export class LogOnClickDirective {

    constructor() {}
    @HostListener('click')
    onClick() { console.log('I am clicked!'); }
}

在模板中簡單寫一句就可以看效果了

<button log-on-click>Click Me</button>

自定義指令使得點擊按鈕會log一條消息
自定義指令使得點擊按鈕會log一條消息

代碼: https://github.com/wpcfan/awesome-tutorials/tree/master/angular2/ng2-tut

慕課網(wǎng) Angular 視頻課上線: http://coding.imooc.com/class/123.html?mc_marking=1fdb7649e8a8143e8b81e221f9621c4a&mc_channel=banner

紙書出版了黑毅,比網(wǎng)上內(nèi)容豐富充實了,歡迎大家訂購钦讳!
京東鏈接:https://item.m.jd.com/product/12059091.html?from=singlemessage&isappinstalled=0

Angular從零到一
Angular從零到一

第一節(jié):初識Angular-CLI
第二節(jié):登錄組件的構(gòu)建
第三節(jié):建立一個待辦事項應(yīng)用
第四節(jié):進化矿瘦!模塊化你的應(yīng)用
第五節(jié):多用戶版本的待辦事項應(yīng)用
第六節(jié):使用第三方樣式庫及模塊優(yōu)化用
第七節(jié):給組件帶來活力
Rx--隱藏在Angular 2.x中利劍
Redux你的Angular 2應(yīng)用
第八節(jié):查缺補漏大合集(上)
第九節(jié):查缺補漏大合集(下)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市愿卒,隨后出現(xiàn)的幾起案子缚去,更是在濱河造成了極大的恐慌,老刑警劉巖琼开,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件易结,死亡現(xiàn)場離奇詭異,居然都是意外死亡柜候,警方通過查閱死者的電腦和手機搞动,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來渣刷,“玉大人鹦肿,你說我怎么就攤上這事「ú瘢” “怎么了箩溃?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵瞭吃,是天一觀的道長。 經(jīng)常有香客問我涣旨,道長歪架,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任霹陡,我火速辦了婚禮和蚪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烹棉。我一直安慰自己惠呼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布峦耘。 她就那樣靜靜地躺著,像睡著了一般旅薄。 火紅的嫁衣襯著肌膚如雪辅髓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天少梁,我揣著相機與錄音洛口,去河邊找鬼。 笑死凯沪,一個胖子當(dāng)著我的面吹牛第焰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播妨马,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挺举,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了烘跺?” 一聲冷哼從身側(cè)響起湘纵,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎滤淳,沒想到半個月后梧喷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡脖咐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年铺敌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屁擅。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡偿凭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出煤蹭,到底是詐尸還是另有隱情笔喉,我是刑警寧澤取视,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站常挚,受9級特大地震影響作谭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奄毡,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一折欠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吼过,春花似錦锐秦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至趟佃,卻和暖如春扇谣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闲昭。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工罐寨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人序矩。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓鸯绿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親簸淀。 傳聞我的和親對象是個殘疾皇子瓶蝴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,078評論 25 707
  • Vue 實例 屬性和方法 每個 Vue 實例都會代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,207評論 0 6
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容租幕。關(guān)于...
    云之外閱讀 5,048評論 0 29
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨立版本囊蓝,Vue即被注冊為全局變量,可以在頁面使用了令蛉。 如果希望搭建...
    Awey閱讀 11,015評論 4 129
  • 被丟在高速公路路口 風(fēng)從八方吹來 把我和一朵云的影子 揉在灰白的巖石上 我攤開手掌 畫上一條小巷 融進綠蔭里 背包...
    有一尾魚閱讀 261評論 3 7