自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

基于Angular 2 CLI開發(fā)CRUD應(yīng)用程序

譯文
開發(fā) 后端
所謂CLI,實(shí)際上是Angular 2新引入的一種命令行操作方式,在這種方式下能夠?qū)ΤR?guī)的Angular 2操作以更快的方式實(shí)現(xiàn)。

【譯者注】本文應(yīng)用開發(fā)及測(cè)試環(huán)境為Mac平臺(tái)(即類Linux環(huán)境);因此,使用Windows平臺(tái)的讀者在使用CLI時(shí)可能需要作一定的調(diào)整。所謂CLI,實(shí)際上是Angular 2新引入的一種命令行操作方式,在這種方式下能夠?qū)ΤR?guī)的Angular 2操作以更快的方式實(shí)現(xiàn)。另外,本文作者使用的Javascript腳本是TypeScript。還有,作者使用了Karma工具(https://karma-runner.github.io/)對(duì)文中的TypeScript腳本進(jìn)行了較全面的單元測(cè)試。因此,雖然本文介紹的是一個(gè)基礎(chǔ)型Angular 2實(shí)例開發(fā)過(guò)程,但是還是值得一讀。

簡(jiǎn)介

Angular 2是一個(gè)世界著名的開源Web前端開發(fā)框架,用于構(gòu)建跨移動(dòng)設(shè)備和桌面平臺(tái)的Web應(yīng)用程序。在本文中,我們將開發(fā)一個(gè)基于Angular 2 CLI方式的Todo Web應(yīng)用程序。這個(gè)程序中實(shí)現(xiàn)的基本功能包括允許用戶:

使用輸入字段快速創(chuàng)建新的todo任務(wù)

切換todo任務(wù)的完成與未完成狀態(tài)

刪除不再需要的todo任務(wù),等等

【注意】本文示例工程源碼下載地址是https://github.com/sitepoint-editors/angular2-todo-app。上述工程的一個(gè)在線展示網(wǎng)址是https://sitepoint-editors.github.io/angular2-todo-app/。下面僅給出這個(gè)程序的一個(gè)靜態(tài)截圖。

Angular CLI簡(jiǎn)介

創(chuàng)建一個(gè)新的Angular 2應(yīng)用程序最簡(jiǎn)單的方法之一是使用全新的Angular命令行界面(CLI)。CLI允許您實(shí)現(xiàn): 生成新的Angular 2應(yīng)用程序的樣板文件代碼

向現(xiàn)有的Angular 2應(yīng)用程序添加指定的功能(包括組件、指令、服務(wù)、管道等)

若要安裝Angular的CLI,請(qǐng)運(yùn)行如下命令:

$ npm install -g angular-cli

這將在您的系統(tǒng)中以全局方式安裝ng命令。

為了驗(yàn)證您的安裝是否成功,您可以運(yùn)行如下命令:

$ ng version

這個(gè)命令應(yīng)會(huì)顯示你已經(jīng)安裝的angular-cli版本號(hào)。更多的細(xì)節(jié),請(qǐng)參考官方安裝說(shuō)明(https://github.com/angular/angular-cli#installation)。

生成Todo應(yīng)用程序

現(xiàn)在,我們已經(jīng)安裝了Angular CLI。下面,我們可以使用它來(lái)生成我們的Todo應(yīng)用程序了,命令如下:

  1. $ ng new angular2-todo-app 

這將創(chuàng)建一個(gè)目錄結(jié)構(gòu),其中包含我們所需要的一切基礎(chǔ)內(nèi)容,如下圖所示:

├── angular-cli-build.js

├── angular-cli.json

├── config

│ ├── environment.dev.ts

│ ├── environment.js

│ ├── environment.prod.ts

│ ├── karma.conf.js

│ ├── karma-test-shim.js

│ └── protractor.conf.js

├── e2e

│ ├── app.e2e-spec.ts

│ ├── app.po.ts

│ ├── tsconfig.json

│ └── typings.d.ts

├── package.json

├── public

├── README.md

├── src

│ ├── app

│ │ ├── app.component.css

│ │ ├── app.component.html

│ │ ├── app.component.spec.ts

│ │ ├── app.component.ts

│ │ ├── environment.ts

│ │ ├── index.ts

│ │ └── shared

│ │ └── index.ts

│ ├── favicon.ico

│ ├── index.html

│ ├── main.ts

│ ├── system-config.ts

│ ├── tsconfig.json

│ └── typings.d.ts

├── tslint.json

├── typings

│ └── ...

└── typings.json

現(xiàn)在,你可以運(yùn)行如下命令:

#切換到CLI剛剛為你創(chuàng)建的新目錄下

  1. $ cd angular2-todo-app 

#啟動(dòng)開發(fā)服務(wù)器

  1. $ ng serve 

上述命令將啟動(dòng)一個(gè)本地開發(fā)服務(wù)器,你可以在你的瀏覽器中導(dǎo)航到如下URL來(lái)觀察你的程序的初始界面:

http://localhost:4200/

使用Angular組件

當(dāng)我們使用ng new命令時(shí),Angular CLI已經(jīng)為我們生成整個(gè)Angular 2應(yīng)用程序的樣板內(nèi)容了。但它并非僅提供這些功能。它還可以幫助我們通過(guò)ng generate命令把其他對(duì)象添加到我們現(xiàn)有的Angular應(yīng)用程序中,命令如下:

  1. # Generate a new component 
  2.  
  3. $ ng generate component my-new-component 
  4.  
  5. # Generate a new directive 
  6.  
  7. $ ng generate directive my-new-directive 
  8.  
  9. # Generate a new pipe 
  10.  
  11. $ ng generate pipe my-new-pipe 
  12.  
  13. # Generate a new service 
  14.  
  15. $ ng generate service my-new-service 
  16.  
  17. # Generate a new class 
  18.  
  19. $ ng generate class my-new-class 
  20.  
  21. # Generate a new interface 
  22.  
  23. $ ng generate interface my-new-interface 
  24.  
  25. # Generate a new enum 
  26.  
  27. $ ng generate enum my-new-enum 

【提示】如果您還不熟悉Angular 2程序中的基本模塊,特別推薦您先讀一下這篇文章(https://angular.io/docs/ts/latest/quickstart.html)。

為了滿足我們的Todo程序的需要,我們還需要實(shí)現(xiàn)如下功能:

 創(chuàng)建一個(gè)Todo類來(lái)描述單個(gè)todo任務(wù)

 創(chuàng)建一個(gè)TodoService服務(wù)來(lái)實(shí)現(xiàn)創(chuàng)建、更新和刪除已有的todo任務(wù)

 開發(fā)一個(gè)TodoApp組件來(lái)顯示用戶界面

下面,讓我們一項(xiàng)一項(xiàng)地完成這些任務(wù)。

創(chuàng)建Todo類

因?yàn)槲覀兪褂玫氖荰ypeScript腳本語(yǔ)言,所以我們可以使用一個(gè)類來(lái)描述Todo任務(wù)項(xiàng)。我們可以通過(guò)Angular CLI命令來(lái)生成一個(gè)Todo類,命令如下:

  1. $ ng generate class Todo 

上述命令將生成如下兩個(gè)文件:

src/app/todo.spec.ts

src/app/todo.ts

讓我們打開文件src/app/todo.ts,并使用如下內(nèi)容替換掉原來(lái)內(nèi)容:

  1. export class Todo { 
  2.  
  3. id: number; 
  4.  
  5. title: string = ''
  6.  
  7. complete: boolean = false
  8.  
  9. constructor(values: Object = {}) { 
  10.  
  11. Object.assign(this, values); 
  12.  
  13.  

每一個(gè)Todo項(xiàng)都有三個(gè)屬性:

 id:數(shù)字類型,對(duì)應(yīng)于todo項(xiàng)的唯一的ID值

 title:字符串類型,對(duì)應(yīng)于todo項(xiàng)的標(biāo)題

 complete:布爾類型,指明當(dāng)前todo項(xiàng)是否已完成

接下來(lái),開始建立構(gòu)造函數(shù)代碼,從而允許我們?cè)趯?shí)例化過(guò)程中指定屬性值:

  1. let todo = new Todo({ 
  2.  
  3. title: 'Read SitePoint article'
  4.  
  5. complete: false 
  6.  
  7. }); 

注意,CLI已經(jīng)為我們生成了文件src/app/todo.spec.ts,所以我們可以添加一個(gè)單元測(cè)試來(lái)確保上述構(gòu)造器按我們的期望結(jié)果那樣工作:

  1. import { 
  2.  
  3. beforeEach, beforeEachProviders, 
  4.  
  5. describe, xdescribe, 
  6.  
  7. expect, it, xit, 
  8.  
  9. async, inject 
  10.  
  11. from '@angular/core/testing'
  12.  
  13. import {Todo} from './todo'
  14.  
  15. describe('Todo', () => { 
  16.  
  17. it('should create an instance', () => { 
  18.  
  19. expect(new Todo()).toBeTruthy(); 
  20.  
  21. }); 
  22.  
  23. it('should accept values in the constructor', () => { 
  24.  
  25. let todo = new Todo({ 
  26.  
  27. title: 'hello'
  28.  
  29. complete: true 
  30.  
  31. }); 
  32.  
  33. expect(todo.title).toEqual('hello'); 
  34.  
  35. expect(todo.complete).toEqual(true); 
  36.  
  37. }); 
  38.  
  39. }); 

為了驗(yàn)證我們的代碼是否按預(yù)期方式工作,我們現(xiàn)在可以運(yùn)行下面的單元測(cè)試命令:

  1. $ ng test 

這個(gè)命令將運(yùn)行Karma程序(https://karma-runner.github.io/)來(lái)運(yùn)行上面我們創(chuàng)建的所有單元測(cè)試代碼。

目前,我們已經(jīng)有了一個(gè)Todo類。接下來(lái),我們要?jiǎng)?chuàng)建Todo服務(wù)來(lái)管理所有todo任務(wù)項(xiàng)。

創(chuàng)建TodoService服務(wù)

TodoService服務(wù)將負(fù)責(zé)管理我們的Todo項(xiàng)目。在以后的文章中,你將會(huì)看到我們?nèi)绾闻cREST API進(jìn)行通信;但現(xiàn)在,我們只是在內(nèi)存中存儲(chǔ)所有的數(shù)據(jù)。

讓我們?cè)俅问褂肁ngular CLI來(lái)生成我們的服務(wù):

  1. $ ng generate service Todo 

生成內(nèi)容如下:

src/app/todo.service.spec.ts

src/app/todo.service.ts

現(xiàn)在,我們可以把todo管理邏輯添加到我們的TodoService了,內(nèi)容如下:

  1. import {Injectable} from '@angular/core'
  2.  
  3. import {Todo} from './todo'
  4.  
  5. @Injectable() 
  6.  
  7. export class TodoService { 
  8.  
  9. // Placeholder for last id so we can simulate 
  10.  
  11. // automatic incrementing of id's 
  12.  
  13. lastId: number = 0; 
  14.  
  15. // Placeholder for todo's 
  16.  
  17. todos: Todo[] = []; 
  18.  
  19. constructor() { 
  20.  
  21.  
  22. // Simulate POST /todos 
  23.  
  24. addTodo(todo: Todo): TodoService { 
  25.  
  26. if (!todo.id) { 
  27.  
  28. todo.id = ++this.lastId; 
  29.  
  30.  
  31. this.todos.push(todo); 
  32.  
  33. return this; 
  34.  
  35.  
  36. // Simulate DELETE /todos/:id 
  37.  
  38. deleteTodoById(id: number): TodoService { 
  39.  
  40. this.todos = this.todos 
  41.  
  42. .filter(todo => todo.id !== id); 
  43.  
  44. return this; 
  45.  
  46.  
  47. // Simulate PUT /todos/:id 
  48.  
  49. updateTodoById(id: number, values: Object = {}): Todo { 
  50.  
  51. let todo = this.getTodoById(id); 
  52.  
  53. if (!todo) { 
  54.  
  55. return null
  56.  
  57.  
  58. Object.assign(todo, values); 
  59.  
  60. return todo; 
  61.  
  62.  
  63. // Simulate GET /todos 
  64.  
  65. getAllTodos(): Todo[] { 
  66.  
  67. return this.todos; 
  68.  
  69.  
  70. // Simulate GET /todos/:id 
  71.  
  72. getTodoById(id: number): Todo { 
  73.  
  74. return this.todos 
  75.  
  76. .filter(todo => todo.id === id) 
  77.  
  78. .pop(); 
  79.  
  80.  
  81. // Toggle todo complete 
  82.  
  83. toggleTodoComplete(todo: Todo){ 
  84.  
  85. let updatedTodo = this.updateTodoById(todo.id, { 
  86.  
  87. complete: !todo.complete 
  88.  
  89. }); 
  90.  
  91. return updatedTodo; 
  92.  
  93.  

就本文目的而言,上述方法的具體實(shí)現(xiàn)細(xì)節(jié)并不至關(guān)重要。關(guān)鍵的內(nèi)容是我們要實(shí)現(xiàn)服務(wù)中的業(yè)務(wù)邏輯。

為了確保我們的邏輯按預(yù)期方式工作,讓我們向文件src/app/todo.service.spec.ts(已經(jīng)由CLI生成)添加單元測(cè)試。

因?yàn)锳ngular CLI已經(jīng)為我們生成了樣板代碼,所以我們只需要實(shí)現(xiàn)測(cè)試即可:

  1. import { 
  2.  
  3. beforeEach, beforeEachProviders, 
  4.  
  5. describe, xdescribe, 
  6.  
  7. expect, it, xit, 
  8.  
  9. async, inject 
  10.  
  11. from '@angular/core/testing'
  12.  
  13. import {Todo} from './todo'
  14.  
  15. import {TodoService} from './todo.service'
  16.  
  17. describe('Todo Service', () => { 
  18.  
  19. beforeEachProviders(() => [TodoService]); 
  20.  
  21. describe('#getAllTodos()', () => { 
  22.  
  23. it('should return an empty array by default', inject([TodoService], (service: TodoService) => { 
  24.  
  25. expect(service.getAllTodos()).toEqual([]); 
  26.  
  27. })); 
  28.  
  29. it('should return all todos', inject([TodoService], (service: TodoService) => { 
  30.  
  31. let todo1 = new Todo({title: 'Hello 1', complete: false}); 
  32.  
  33. let todo2 = new Todo({title: 'Hello 2', complete: true}); 
  34.  
  35. service.addTodo(todo1); 
  36.  
  37. service.addTodo(todo2); 
  38.  
  39. expect(service.getAllTodos()).toEqual([todo1, todo2]); 
  40.  
  41. })); 
  42.  
  43. }); 
  44.  
  45. describe('#save(todo)', () => { 
  46.  
  47. it('should automatically assign an incrementing id', inject([TodoService], (service: TodoService) => { 
  48.  
  49. let todo1 = new Todo({title: 'Hello 1', complete: false}); 
  50.  
  51. let todo2 = new Todo({title: 'Hello 2', complete: true}); 
  52.  
  53. service.addTodo(todo1); 
  54.  
  55. service.addTodo(todo2); 
  56.  
  57. expect(service.getTodoById(1)).toEqual(todo1); 
  58.  
  59. expect(service.getTodoById(2)).toEqual(todo2); 
  60.  
  61. })); 
  62.  
  63. }); 
  64.  
  65. describe('#deleteTodoById(id)', () => { 
  66.  
  67. it('should remove todo with the corresponding id', inject([TodoService], (service: TodoService) => { 
  68.  
  69. let todo1 = new Todo({title: 'Hello 1', complete: false}); 
  70.  
  71. let todo2 = new Todo({title: 'Hello 2', complete: true}); 
  72.  
  73. service.addTodo(todo1); 
  74.  
  75. service.addTodo(todo2); 
  76.  
  77. expect(service.getAllTodos()).toEqual([todo1, todo2]); 
  78.  
  79. service.deleteTodoById(1); 
  80.  
  81. expect(service.getAllTodos()).toEqual([todo2]); 
  82.  
  83. service.deleteTodoById(2); 
  84.  
  85. expect(service.getAllTodos()).toEqual([]); 
  86.  
  87. })); 
  88.  
  89. it('should not removing anything if todo with corresponding id is not found', inject([TodoService], (service: TodoService) => { 
  90.  
  91. let todo1 = new Todo({title: 'Hello 1', complete: false}); 
  92.  
  93. let todo2 = new Todo({title: 'Hello 2', complete: true}); 
  94.  
  95. service.addTodo(todo1); 
  96.  
  97. service.addTodo(todo2); 
  98.  
  99. expect(service.getAllTodos()).toEqual([todo1, todo2]); 
  100.  
  101. service.deleteTodoById(3); 
  102.  
  103. expect(service.getAllTodos()).toEqual([todo1, todo2]); 
  104.  
  105. })); 
  106.  
  107. }); 
  108.  
  109. describe('#updateTodoById(id, values)', () => { 
  110.  
  111. it('should return todo with the corresponding id and updated data', inject([TodoService], (service: TodoService) => { 
  112.  
  113. let todo = new Todo({title: 'Hello 1', complete: false}); 
  114.  
  115. service.addTodo(todo); 
  116.  
  117. let updatedTodo = service.updateTodoById(1, { 
  118.  
  119. title: 'new title' 
  120.  
  121. }); 
  122.  
  123. expect(updatedTodo.title).toEqual('new title'); 
  124.  
  125. })); 
  126.  
  127. it('should return null if todo is not found', inject([TodoService], (service: TodoService) => { 
  128.  
  129. let todo = new Todo({title: 'Hello 1', complete: false}); 
  130.  
  131. service.addTodo(todo); 
  132.  
  133. let updatedTodo = service.updateTodoById(2, { 
  134.  
  135. title: 'new title' 
  136.  
  137. }); 
  138.  
  139. expect(updatedTodo).toEqual(null); 
  140.  
  141. })); 
  142.  
  143. }); 
  144.  
  145. describe('#toggleTodoComplete(todo)', () => { 
  146.  
  147. it('should return the updated todo with inverse complete status', inject([TodoService], (service: TodoService) => { 
  148.  
  149. let todo = new Todo({title: 'Hello 1', complete: false}); 
  150.  
  151. service.addTodo(todo); 
  152.  
  153. let updatedTodo = service.toggleTodoComplete(todo); 
  154.  
  155. expect(updatedTodo.complete).toEqual(true); 
  156.  
  157. service.toggleTodoComplete(todo); 
  158.  
  159. expect(updatedTodo.complete).toEqual(false); 
  160.  
  161. })); 
  162.  
  163. }); 
  164.  
  165. }); 

【提示】Karma工具中預(yù)配置了Jasmine(https://github.com/jasmine/jasmine),你可以閱讀資料http://jasmine.github.io/2.4/introduction.html來(lái)更多地了解有關(guān)它的語(yǔ)法。

為了校驗(yàn)我們編寫的業(yè)務(wù)邏輯都是有效的,讓我們?cè)賮?lái)運(yùn)行單元測(cè)試:

  1. $ ng test 

現(xiàn)在,既然我們已經(jīng)有了一個(gè)可以使用的TodoService,那么接下來(lái)我們要實(shí)現(xiàn)程序的UI部分了。

值得注意的是,在Angular 2中,部分界面是使用組件(Components)來(lái)描述的。

創(chuàng)建TodoApp組件

讓我們?cè)僖淮问褂肅LI來(lái)生成我們所需要的程序組件吧:

  1. $ ng generate component TodoApp 

上述命令生成內(nèi)容如下:

  1. src/app/todo-app/todo-app.component.css 
  2.  
  3. src/app/todo-app/todo-app.component.html 
  4.  
  5. src/app/todo-app/todo-app.component.spec.ts 
  6.  
  7. src/app/todo-app/todo-app.component.ts 
  8.  
  9. src/app/todo-app/index.ts 

【提示】 模板和樣式可以在內(nèi)聯(lián)的腳本文件內(nèi)指定。默認(rèn)情況下,Angular的CLI將創(chuàng)建單獨(dú)的文件;所以,在這篇文章中我們也是使用單獨(dú)的文件。

接下來(lái),讓我們把組件的視圖添加到文件src/app/todo-app/todo-app.component.html中:

  1. <section class="todoapp"
  2.  
  3. <header class="header"
  4.  
  5. <h1>Todos</h1> 
  6.  
  7. <input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodo.title" (keyup.enter)="addTodo()"
  8.  
  9. </header> 
  10.  
  11. <section class="main" *ngIf="todos.length > 0"
  12.  
  13. <ul class="todo-list"
  14.  
  15. <li *ngFor="let todo of todos" [class.completed]="todo.complete"
  16.  
  17. <div class="view"
  18.  
  19. <input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"
  20.  
  21. <label>{{todo.title}}</label> 
  22.  
  23. <button class="destroy" (click)="removeTodo(todo)"></button> 
  24.  
  25. </div> 
  26.  
  27. </li> 
  28.  
  29. </ul> 
  30.  
  31. </section
  32.  
  33. <footer class="footer" *ngIf="todos.length > 0"
  34.  
  35. <span class="todo-count"><strong>{{todos.length}}</strong> {{todos.length == 1 ? 'item' : 'items'}} left</span> 
  36.  
  37. </footer> 
  38.  
  39. </section

在此,我們使用了Angular的超級(jí)短小的模板語(yǔ)法表達(dá)方式——而這是你以前從未遇到過(guò)的:

 [property]="expression":把屬性設(shè)置為expression的結(jié)果

(event)=”statement”:當(dāng)事情發(fā)生時(shí)執(zhí)行statement

 [(property)]="expression":使用expression創(chuàng)建雙向綁定

 [class.special]="expression":當(dāng)expression為真時(shí)在元素上添加special類

[style.color]="expression":把css屬性color設(shè)置為expression的結(jié)果

提示】如果你還不熟悉Angular的模板語(yǔ)法,那么你應(yīng)當(dāng)閱讀一下官方有關(guān)文檔,地址是https://angular.io/docs/ts/latest/guide/template-syntax.html。

下面,讓我們具體地看一下上面的代碼對(duì)我們的視圖的影響。首先,在頂部使用了一個(gè)Input控件來(lái)創(chuàng)建一個(gè)新的todo項(xiàng):

  1. <input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodo.title" (keyup.enter)="addTodo()"

在這里:

 [(ngModel)]="newTodo.title":在input值與newTodo.title之間創(chuàng)建一個(gè)雙向綁定。

 (keyup.enter)=”addTodo()”:在Input控件中輸入內(nèi)容并在按下回車時(shí)告訴Angular執(zhí)行addTodo()命令。

【提示】目前你先不用擔(dān)心newTodo和addTodo()的存在問(wèn)題,稍后會(huì)做這項(xiàng)工作?,F(xiàn)在,只需盡力弄懂視圖語(yǔ)義即可。

接下來(lái),使用一個(gè)節(jié)顯示todo部分:

  1. <section class="main" *ngIf="todos.length > 0"

其中,*ngIf="todos.length > 0"的含義是:當(dāng)至少有一個(gè)todo項(xiàng)時(shí),僅顯示section部分及其所有后代節(jié)點(diǎn)的內(nèi)容。

在該節(jié)中,我們要求Angular為每一個(gè)todo生成一個(gè)li元素:

  1. <li *ngFor="let todo of todos" [class.completed]="todo.complete"

其中:

 *ngFor="let todo of todos":遍歷所有的todo并在每一次循環(huán)中把當(dāng)前todo賦值給一個(gè)命名為todo的變量。

 [class.completed]="todo.complete":當(dāng)todo.complete為真時(shí)把CSS類completed應(yīng)用于元素li。

最后,我們通過(guò)ngFor循環(huán)顯示每一個(gè)todo項(xiàng)目的詳細(xì)信息:

  1. <div class="view"
  2.  
  3. <input class="toggle" type="checkbox" (click)="toggleTodoComplete(todo)" [checked]="todo.complete"
  4.  
  5. <label>{{todo.title}}</label> 
  6.  
  7. <button class="destroy" (click)="removeTodo(todo)"></button> 
  8.  
  9. </div> 

在這里:

 (click)="toggleTodoComplete(todo)":當(dāng)勾選復(fù)選框時(shí)執(zhí)行toggleTodoComplete(todo)

 [checked]="todo.complete":把值todo.complete賦給元素的checked屬性

 (click)="removeTodo(todo)":當(dāng)點(diǎn)擊刪除按鈕時(shí)執(zhí)行removeTodo(todo)

好,讓我們稍微喘口氣吧。到此我們已經(jīng)使用了不少新的語(yǔ)法格式。

你可能想知道像addTodo()和newTodo.title這樣的表達(dá)式是如何計(jì)算的。到目前,我們還沒(méi)有定義它們,那么Angular是如何理解我們的意圖的呢?

這正是表達(dá)式上下文(expression context)產(chǎn)生的原因。一個(gè)組件的表達(dá)式上下文就是組件實(shí)例。而組件實(shí)例就是組件類的一個(gè)實(shí)例。

我們的TodoAppComponent的組件類定義于文件src/app/todo-app/todo-app.component.ts中。

Angular CLI已經(jīng)為我們的TodoAppComponent類創(chuàng)建了模板,代碼如下:

  1. import { Component } from '@angular/core'
  2.  
  3. @Component({ 
  4.  
  5. moduleId: module.id, 
  6.  
  7. selector: 'app-todo-app'
  8.  
  9. templateUrl: 'todo-app.component.html'
  10.  
  11. styleUrls: ['todo-app.component.css'
  12.  
  13. }) 
  14.  
  15. export class TodoAppComponent { 
  16.  
  17. constructor() {} 
  18.  

所以,我們可以馬上開始加入我們自定義的邏輯。我們將需要TodoService實(shí)例;因此,讓我們開始將它注入到我們的組件中。

首先,我們導(dǎo)入TodoService類,并在組件的修飾詞數(shù)組部分指定它:

  1. // Import class so we can register it as dependency injection token 
  2.  
  3. import {TodoService} from '../todo.service'
  4.  
  5. @Component({ 
  6.  
  7. // ... 
  8.  
  9. providers: [TodoService] 
  10.  
  11. }) 
  12.  
  13. export class TodoAppComponent { 
  14.  
  15. // ... 
  16.  

TodoAppComponent的依賴注入器現(xiàn)在能夠識(shí)別出TodoService類為依賴性注入符號(hào)并在我們要求時(shí)返回TodoService的單一實(shí)例。

【提示】Angular的依賴注入系統(tǒng)能夠接受各種各樣的依賴項(xiàng)注入。上述語(yǔ)法只是類提供器(Class Provider:使用單例模式提供依賴性)格式的一個(gè)速記表示。有關(guān)此內(nèi)容更多的細(xì)節(jié),請(qǐng)參考官方的網(wǎng)址https://angular.io/docs/ts/latest/guide/dependency-injection.html。

現(xiàn)在,組件的依賴注入器知道它需要提供什么了,我們要求它通過(guò)在TodoAppComponent構(gòu)造函數(shù)中指定依賴項(xiàng)來(lái)在我們的組件中注入TodoService實(shí)例:

  1. // Import class so we can use it as dependency injection token in the constructor 
  2.  
  3. import {TodoService} from '../todo.service'
  4.  
  5. @Component({ 
  6.  
  7. // ... 
  8.  
  9. }) 
  10.  
  11. export class TodoAppComponent { 
  12.  
  13. // Ask Angular DI system to inject the dependency 
  14.  
  15. // associated with the dependency injection token `TodoService` 
  16.  
  17. // and assign it to a property called `todoService` 
  18.  
  19. constructor(private todoService: TodoService) { 
  20.  
  21.  
  22. // Service is now available as this.todoService 
  23.  
  24. toggleTodoComplete(todo) { 
  25.  
  26. this.todoService.toggleTodoComplete(todo); 
  27.  
  28.  

現(xiàn)在,我們可以實(shí)現(xiàn)我們的視圖中需要的所有邏輯了。為此,只需要向我們 TodoAppComponent類中添加屬性和方法就可以了:

  1. import {Component} from '@angular/core'
  2.  
  3. import {Todo} from '../todo'
  4.  
  5. import {TodoService} from '../todo.service'
  6.  
  7. @Component({ 
  8.  
  9. moduleId: module.id, 
  10.  
  11. selector: 'todo-app'
  12.  
  13. templateUrl: 'todo-app.component.html'
  14.  
  15. styleUrls: ['todo-app.component.css'], 
  16.  
  17. providers: [TodoService] 
  18.  
  19. }) 
  20.  
  21. export class TodoAppComponent { 
  22.  
  23. newTodo: Todo = new Todo(); 
  24.  
  25. constructor(private todoService: TodoService) { 
  26.  
  27.  
  28. addTodo() { 
  29.  
  30. this.todoService.addTodo(this.newTodo); 
  31.  
  32. this.newTodo = new Todo(); 
  33.  
  34.  
  35. toggleTodoComplete(todo) { 
  36.  
  37. this.todoService.toggleTodoComplete(todo); 
  38.  
  39.  
  40. removeTodo(todo) { 
  41.  
  42. this.todoService.deleteTodoById(todo.id); 
  43.  
  44.  
  45. get todos() { 
  46.  
  47. return this.todoService.getAllTodos(); 
  48.  
  49.  

當(dāng)組件類實(shí)例化時(shí),我們首先實(shí)例化一個(gè)newTodo屬性并分配新的Todo()。下面的代碼展示了在我們的視圖中添加的雙向綁定到的newTodo:

  1. <input class="new-todo" placeholder="What needs to be done?" autofocus="" [(ngModel)]="newTodo.title" (keyup.enter)="addTodo()"

無(wú)論視圖中的輸入值何時(shí)改變,組件實(shí)例中的值都被更新。而無(wú)論組件實(shí)例中的輸入值何時(shí)改變,視圖中的輸入元素中的值都將更改。

接下來(lái),我們要實(shí)現(xiàn)我們的視圖中使用的所有方法。

它們的具體實(shí)現(xiàn)代碼很短,應(yīng)該是不需要給予過(guò)多解釋的,因?yàn)槲覀円呀?jīng)把所有業(yè)務(wù)邏輯委派到todoService了。

【提示】把業(yè)務(wù)邏輯委派到一個(gè)專門的服務(wù)中是一種良好的編程實(shí)踐,因?yàn)樗刮覀兡軌蚣芯芾砗蜏y(cè)試業(yè)務(wù)邏輯。

最后,在結(jié)束本教程前,讓我們來(lái)了解一下Angular CLI的最后一個(gè)很酷的功能吧。

部署到GitHub網(wǎng)站

Angular的CLI使得將我們的應(yīng)用部署到GitHub頁(yè)變得超級(jí)簡(jiǎn)單——使用類似于下面的這樣一個(gè)命令即可搞定:

  1. $ ng github-pages:deploy --message 'deploy(dist): deploy on GitHub pages' 

這個(gè)github-pages:deploy命令告訴Angular CLI生成我們的Angular應(yīng)用的一個(gè)靜態(tài)版本,并將它推送到我們的GitHub倉(cāng)庫(kù)的gh-pages分支下。相應(yīng)的輸出結(jié)果如下所示:

  1. $ ng github-pages:deploy --message 'deploy(dist): deploy on GitHub pages' 
  2.  
  3. Built project successfully. Stored in "dist/"
  4.  
  5. Deployed! Visit https://sitepoint-editors.github.io/angular2-todo-app/ 
  6.  
  7. Github pages might take a few minutes to show the deployed site. 

現(xiàn)在,我們的應(yīng)用程序可以通過(guò)網(wǎng)站地址https://sitepoint-editors.github.io/angular2-todo-app/進(jìn)行訪問(wèn)了。

趕快去打開這個(gè)網(wǎng)址去試試吧。

小結(jié)

Angular 2無(wú)疑是一只猛獸!一只非常強(qiáng)大的猛獸!

在本文中,我向你介紹了很多很多?,F(xiàn)在,讓我們回顧一下我們?cè)谶@篇文章中所學(xué)到的內(nèi)容吧:

我們學(xué)習(xí)了如何安裝Angular CLI并了解了在創(chuàng)建新的應(yīng)用程序或添加現(xiàn)有應(yīng)用程序的新特征時(shí)它如何節(jié)約我們的時(shí)間。

我們學(xué)習(xí)了如何在一個(gè)Angular服務(wù)中實(shí)現(xiàn)業(yè)務(wù)邏輯以及如何使用單元測(cè)試來(lái)測(cè)試我們的業(yè)務(wù)邏輯。

我們學(xué)習(xí)了如何使用組件與用戶交互以及如何使用依賴注入委派邏輯到服務(wù)中。

我們學(xué)習(xí)了Angular模板語(yǔ)法基礎(chǔ)知識(shí),并簡(jiǎn)要地談?wù)摿薃ngular依賴項(xiàng)注入的工作原理。

最后,我們學(xué)習(xí)了如何把我們的應(yīng)用程序快速部署到GitHub網(wǎng)頁(yè)。

在以后的文章中,我們還有很多有關(guān)Angular 2的內(nèi)容探討,例如:

使用Angular 2 HTTP服務(wù)與REST API后端進(jìn)行通信

使用Angular管道功能過(guò)濾todo內(nèi)容

通過(guò)路由來(lái)使本文中的應(yīng)用變成一個(gè)多頁(yè)式應(yīng)用程序

以及其他更多更多……

所以,敬請(qǐng)期待更多的關(guān)于Angular 2這個(gè)奇妙的世界吧。

責(zé)任編輯:趙立京 來(lái)源: 51CTO
相關(guān)推薦

2013-11-19 15:35:01

2015-01-06 09:59:59

云應(yīng)用程序Java開發(fā)SQL

2010-09-29 09:54:09

J2ME應(yīng)用程序

2010-10-09 16:13:10

J2ME應(yīng)用程序

2016-07-29 13:47:05

RethinkDBWeb

2013-02-21 14:14:40

開發(fā)Tizen

2013-02-21 14:15:41

開發(fā)Tizen

2012-02-08 15:06:31

ibmdw

2022-09-19 00:37:13

SaaS云計(jì)算開發(fā)

2009-09-22 12:25:04

ibmdwDB2

2009-03-12 10:22:27

EclipseJ2MEJDT

2022-02-24 16:39:41

OpenHarmonNiobe開發(fā)鴻蒙

2024-03-22 11:40:40

Node.jsNodeCRUD

2011-02-22 10:23:43

2011-03-31 13:15:18

BlackBerry

2018-12-11 11:41:14

物聯(lián)網(wǎng)應(yīng)用程序IOT

2011-12-06 10:10:59

云計(jì)算移動(dòng)應(yīng)用

2009-09-24 17:21:17

加速Hibernate

2010-10-15 09:39:22

MeeGoQt

2011-07-21 16:19:30

iOS Twitter
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)