精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

基于Angular 2 CLI開發CRUD應用程序

譯文
開發 后端
所謂CLI,實際上是Angular 2新引入的一種命令行操作方式,在這種方式下能夠對常規的Angular 2操作以更快的方式實現。

【譯者注】本文應用開發及測試環境為Mac平臺(即類Linux環境);因此,使用Windows平臺的讀者在使用CLI時可能需要作一定的調整。所謂CLI,實際上是Angular 2新引入的一種命令行操作方式,在這種方式下能夠對常規的Angular 2操作以更快的方式實現。另外,本文作者使用的Javascript腳本是TypeScript。還有,作者使用了Karma工具(https://karma-runner.github.io/)對文中的TypeScript腳本進行了較全面的單元測試。因此,雖然本文介紹的是一個基礎型Angular 2實例開發過程,但是還是值得一讀。

簡介

Angular 2是一個世界著名的開源Web前端開發框架,用于構建跨移動設備和桌面平臺的Web應用程序。在本文中,我們將開發一個基于Angular 2 CLI方式的Todo Web應用程序。這個程序中實現的基本功能包括允許用戶:

使用輸入字段快速創建新的todo任務

切換todo任務的完成與未完成狀態

刪除不再需要的todo任務,等等

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

Angular CLI簡介

創建一個新的Angular 2應用程序最簡單的方法之一是使用全新的Angular命令行界面(CLI)。CLI允許您實現: 生成新的Angular 2應用程序的樣板文件代碼

向現有的Angular 2應用程序添加指定的功能(包括組件、指令、服務、管道等)

若要安裝Angular的CLI,請運行如下命令:

$ npm install -g angular-cli

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

為了驗證您的安裝是否成功,您可以運行如下命令:

$ ng version

這個命令應會顯示你已經安裝的angular-cli版本號。更多的細節,請參考官方安裝說明(https://github.com/angular/angular-cli#installation)。

生成Todo應用程序

現在,我們已經安裝了Angular CLI。下面,我們可以使用它來生成我們的Todo應用程序了,命令如下:

  1. $ ng new angular2-todo-app 

這將創建一個目錄結構,其中包含我們所需要的一切基礎內容,如下圖所示:

├── 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

現在,你可以運行如下命令:

#切換到CLI剛剛為你創建的新目錄下

  1. $ cd angular2-todo-app 

#啟動開發服務器

  1. $ ng serve 

上述命令將啟動一個本地開發服務器,你可以在你的瀏覽器中導航到如下URL來觀察你的程序的初始界面:

http://localhost:4200/

使用Angular組件

當我們使用ng new命令時,Angular CLI已經為我們生成整個Angular 2應用程序的樣板內容了。但它并非僅提供這些功能。它還可以幫助我們通過ng generate命令把其他對象添加到我們現有的Angular應用程序中,命令如下:

  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程序的需要,我們還需要實現如下功能:

 創建一個Todo類來描述單個todo任務

 創建一個TodoService服務來實現創建、更新和刪除已有的todo任務

 開發一個TodoApp組件來顯示用戶界面

下面,讓我們一項一項地完成這些任務。

創建Todo類

因為我們使用的是TypeScript腳本語言,所以我們可以使用一個類來描述Todo任務項。我們可以通過Angular CLI命令來生成一個Todo類,命令如下:

  1. $ ng generate class Todo 

上述命令將生成如下兩個文件:

src/app/todo.spec.ts

src/app/todo.ts

讓我們打開文件src/app/todo.ts,并使用如下內容替換掉原來內容:

  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.  

每一個Todo項都有三個屬性:

 id:數字類型,對應于todo項的唯一的ID值

 title:字符串類型,對應于todo項的標題

 complete:布爾類型,指明當前todo項是否已完成

接下來,開始建立構造函數代碼,從而允許我們在實例化過程中指定屬性值:

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

注意,CLI已經為我們生成了文件src/app/todo.spec.ts,所以我們可以添加一個單元測試來確保上述構造器按我們的期望結果那樣工作:

  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. }); 

為了驗證我們的代碼是否按預期方式工作,我們現在可以運行下面的單元測試命令:

  1. $ ng test 

這個命令將運行Karma程序(https://karma-runner.github.io/)來運行上面我們創建的所有單元測試代碼。

目前,我們已經有了一個Todo類。接下來,我們要創建Todo服務來管理所有todo任務項。

創建TodoService服務

TodoService服務將負責管理我們的Todo項目。在以后的文章中,你將會看到我們如何與REST API進行通信;但現在,我們只是在內存中存儲所有的數據。

讓我們再次使用Angular CLI來生成我們的服務:

  1. $ ng generate service Todo 

生成內容如下:

src/app/todo.service.spec.ts

src/app/todo.service.ts

現在,我們可以把todo管理邏輯添加到我們的TodoService了,內容如下:

  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.  

就本文目的而言,上述方法的具體實現細節并不至關重要。關鍵的內容是我們要實現服務中的業務邏輯。

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

因為Angular CLI已經為我們生成了樣板代碼,所以我們只需要實現測試即可:

  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工具中預配置了Jasmine(https://github.com/jasmine/jasmine),你可以閱讀資料http://jasmine.github.io/2.4/introduction.html來更多地了解有關它的語法。

為了校驗我們編寫的業務邏輯都是有效的,讓我們再來運行單元測試:

  1. $ ng test 

現在,既然我們已經有了一個可以使用的TodoService,那么接下來我們要實現程序的UI部分了。

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

創建TodoApp組件

讓我們再一次使用CLI來生成我們所需要的程序組件吧:

  1. $ ng generate component TodoApp 

上述命令生成內容如下:

  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 

【提示】 模板和樣式可以在內聯的腳本文件內指定。默認情況下,Angular的CLI將創建單獨的文件;所以,在這篇文章中我們也是使用單獨的文件。

接下來,讓我們把組件的視圖添加到文件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的超級短小的模板語法表達方式——而這是你以前從未遇到過的:

 [property]="expression":把屬性設置為expression的結果

(event)=”statement”:當事情發生時執行statement

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

 [class.special]="expression":當expression為真時在元素上添加special類

[style.color]="expression":把css屬性color設置為expression的結果

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

下面,讓我們具體地看一下上面的代碼對我們的視圖的影響。首先,在頂部使用了一個Input控件來創建一個新的todo項:

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

在這里:

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

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

【提示】目前你先不用擔心newTodo和addTodo()的存在問題,稍后會做這項工作?,F在,只需盡力弄懂視圖語義即可。

接下來,使用一個節顯示todo部分:

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

其中,*ngIf="todos.length > 0"的含義是:當至少有一個todo項時,僅顯示section部分及其所有后代節點的內容。

在該節中,我們要求Angular為每一個todo生成一個li元素:

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

其中:

 *ngFor="let todo of todos":遍歷所有的todo并在每一次循環中把當前todo賦值給一個命名為todo的變量。

 [class.completed]="todo.complete":當todo.complete為真時把CSS類completed應用于元素li。

最后,我們通過ngFor循環顯示每一個todo項目的詳細信息:

  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)":當勾選復選框時執行toggleTodoComplete(todo)

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

 (click)="removeTodo(todo)":當點擊刪除按鈕時執行removeTodo(todo)

好,讓我們稍微喘口氣吧。到此我們已經使用了不少新的語法格式。

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

這正是表達式上下文(expression context)產生的原因。一個組件的表達式上下文就是組件實例。而組件實例就是組件類的一個實例。

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

Angular CLI已經為我們的TodoAppComponent類創建了模板,代碼如下:

  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實例;因此,讓我們開始將它注入到我們的組件中。

首先,我們導入TodoService類,并在組件的修飾詞數組部分指定它:

  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的依賴注入器現在能夠識別出TodoService類為依賴性注入符號并在我們要求時返回TodoService的單一實例。

【提示】Angular的依賴注入系統能夠接受各種各樣的依賴項注入。上述語法只是類提供器(Class Provider:使用單例模式提供依賴性)格式的一個速記表示。有關此內容更多的細節,請參考官方的網址https://angular.io/docs/ts/latest/guide/dependency-injection.html。

現在,組件的依賴注入器知道它需要提供什么了,我們要求它通過在TodoAppComponent構造函數中指定依賴項來在我們的組件中注入TodoService實例:

  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.  

現在,我們可以實現我們的視圖中需要的所有邏輯了。為此,只需要向我們 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.  

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

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

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

接下來,我們要實現我們的視圖中使用的所有方法。

它們的具體實現代碼很短,應該是不需要給予過多解釋的,因為我們已經把所有業務邏輯委派到todoService了。

【提示】把業務邏輯委派到一個專門的服務中是一種良好的編程實踐,因為它使我們能夠集中精力管理和測試業務邏輯。

最后,在結束本教程前,讓我們來了解一下Angular CLI的最后一個很酷的功能吧。

部署到GitHub網站

Angular的CLI使得將我們的應用部署到GitHub頁變得超級簡單——使用類似于下面的這樣一個命令即可搞定:

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

這個github-pages:deploy命令告訴Angular CLI生成我們的Angular應用的一個靜態版本,并將它推送到我們的GitHub倉庫的gh-pages分支下。相應的輸出結果如下所示:

  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. 

現在,我們的應用程序可以通過網站地址https://sitepoint-editors.github.io/angular2-todo-app/進行訪問了。

趕快去打開這個網址去試試吧。

小結

Angular 2無疑是一只猛獸!一只非常強大的猛獸!

在本文中,我向你介紹了很多很多?,F在,讓我們回顧一下我們在這篇文章中所學到的內容吧:

我們學習了如何安裝Angular CLI并了解了在創建新的應用程序或添加現有應用程序的新特征時它如何節約我們的時間。

我們學習了如何在一個Angular服務中實現業務邏輯以及如何使用單元測試來測試我們的業務邏輯。

我們學習了如何使用組件與用戶交互以及如何使用依賴注入委派邏輯到服務中。

我們學習了Angular模板語法基礎知識,并簡要地談論了Angular依賴項注入的工作原理。

最后,我們學習了如何把我們的應用程序快速部署到GitHub網頁。

在以后的文章中,我們還有很多有關Angular 2的內容探討,例如:

使用Angular 2 HTTP服務與REST API后端進行通信

使用Angular管道功能過濾todo內容

通過路由來使本文中的應用變成一個多頁式應用程序

以及其他更多更多……

所以,敬請期待更多的關于Angular 2這個奇妙的世界吧。

責任編輯:趙立京 來源: 51CTO
相關推薦

2013-11-19 15:35:01

2015-01-06 09:59:59

云應用程序Java開發SQL

2010-10-09 16:13:10

J2ME應用程序

2010-09-29 09:54:09

J2ME應用程序

2012-02-08 15:06:31

ibmdw

2022-09-19 00:37:13

SaaS云計算開發

2013-02-21 14:14:40

開發Tizen

2013-02-21 14:15:41

開發Tizen

2016-07-29 13:47:05

RethinkDBWeb

2009-09-22 12:25:04

ibmdwDB2

2009-03-12 10:22:27

EclipseJ2MEJDT

2022-02-24 16:39:41

OpenHarmonNiobe開發鴻蒙

2010-10-15 09:39:22

MeeGoQt

2009-09-24 17:21:17

加速Hibernate

2009-07-17 16:09:29

Swing桌面應用程序

2011-05-31 13:34:22

應用開發iPad

2013-08-08 09:48:10

Web

2011-07-21 16:19:30

iOS Twitter

2018-12-11 11:41:14

物聯網應用程序IOT

2011-03-31 13:15:18

BlackBerry
點贊
收藏

51CTO技術棧公眾號

久久精品中文字幕一区二区三区| 久久久久www| 日韩欧美在线播放视频| 51调教丨国产调教视频| www.视频在线.com| 精品亚洲免费视频| 欧美老少做受xxxx高潮| 97香蕉碰碰人妻国产欧美| 欧美三级精品| 国产不卡免费视频| 日本精品视频在线| 亚洲国产精品免费在线观看| 日日天天久久| 制服丝袜国产精品| 国产日产欧美视频| 特级毛片在线| 中文字幕乱码亚洲精品一区| 北条麻妃高清一区| 天天操天天干天天摸| 久久久久久久久久久久久久久久久久久久| 一道本成人在线| 可以在线看黄的网站| 久久电影视频| 宅男噜噜噜66国产日韩在线观看| 这里只有精品视频| 先锋资源av在线| 国产一区二区三区免费在线 | 国产日产在线观看| 日韩av资源网| 精品美女在线播放| 在线观看av免费观看| 日日夜夜天天综合| 精品国产乱码久久久久久天美| 亚洲精品一区二| 美女毛片在线看| fc2成人免费人成在线观看播放 | 日韩va欧美va亚洲va久久| 亚洲成人性视频| 91小视频在线播放| 成人亚洲网站| 欧美综合亚洲图片综合区| www国产精品内射老熟女| 欧美人体视频xxxxx| 亚洲男人的天堂av| 亚洲一区二区免费在线| 艳妇乳肉豪妇荡乳av无码福利| 国产精品美女久久久| 高清欧美性猛交xxxx| 91超薄肉色丝袜交足高跟凉鞋| 欧美人与动牲性行为| 亚洲欧美一区二区三区国产精品 | 日批免费观看视频| 日韩亚洲精品在线观看| 欧美一级在线免费| 亚洲综合123| 精品一区二区三区四区五区| 欧美一区二区三区视频免费| 亚洲五月激情网| 91麻豆精品国产综合久久久| 欧美日本一区二区三区| 一起操在线视频| 欧美综合影院| 欧美一级片在线看| 自拍视频第一页| 极品束缚调教一区二区网站| 亚洲精品国产综合区久久久久久久| 又粗又黑又大的吊av| 美洲精品一卡2卡三卡4卡四卡| 一区二区在线观看免费 | 国产精品久久久免费| 奇米4444一区二区三区| 中文字幕在线日本| 久久精品国产77777蜜臀| 91亚洲va在线va天堂va国| 精品国自产在线观看| 成年人午夜久久久| 国产精品美女免费视频| 一级黄色片在线观看| 国产在线精品不卡| 国产精品一区二| 视频一区二区在线播放| 九色综合狠狠综合久久| 亚洲free嫩bbb| 狠狠人妻久久久久久综合麻豆| 99视频精品在线| 涩涩日韩在线| 婷婷av一区二区三区| 麻豆精品国产91久久久久久| 成人午夜在线影院| 日韩一级在线播放| 久久久国际精品| 99精品视频网站| 国产在线视频福利| 亚洲品质自拍视频网站| 久久久久免费看黄a片app| 日韩精品免费观看视频| 日韩欧美123| 国产又大又粗又爽的毛片| 亚洲精品成人影院| 欧美在线日韩在线| 国产男女裸体做爰爽爽| 91视频免费播放| 异国色恋浪漫潭| xx欧美xxx| 日韩欧美国产综合一区| 久久久久久亚洲中文字幕无码| 久久精品影视| 青青精品视频播放| 国产成人麻豆精品午夜在线 | 亚洲一区免费视频| 精品久久久久久无码国产| 最新精品在线| 视频在线一区二区| 国产精品乱子伦| 国产精品1区2区| 亚洲精品9999| 二区三区不卡| 亚洲国产99精品国自产| 看免费黄色录像| 奇米影视一区二区三区| 精品视频一区二区| 51xtv成人影院| 欧美色国产精品| 在线免费观看麻豆| 香蕉国产精品| 国产精品美女免费视频| 免费看男男www网站入口在线| 亚洲一区二区三区四区五区中文| 亚洲一级免费在线观看| 国产精品av一区二区三区| 日韩精品资源二区在线| 中文乱码字幕高清一区二区| 亚州av乱码久久精品蜜桃| 国产精品av在线| 色猫av在线| 精品久久久久久久久国产字幕| 欧美日韩理论片| 四虎国产精品免费观看| 国产精品久久婷婷六月丁香| 蜜桃成人在线视频| 欧美性黄网官网| 日本japanese极品少妇| 亚洲精选久久| 精品一卡二卡三卡四卡日本乱码| 黄色小说在线播放| 欧美电影免费提供在线观看| 亚洲av无码一区二区三区在线| 九色|91porny| 91麻豆天美传媒在线| 精品国产亚洲一区二区三区在线| 久久久国产在线视频| 国产免费黄色录像| 日韩美女视频19| 日本高清一区二区视频| 中文视频一区| 99porn视频在线| 国产丝袜精品丝袜| 亚洲精品久久视频| 午夜毛片在线观看| 久久久蜜臀国产一区二区| 亚洲熟妇av一区二区三区| 精品一区二区三区中文字幕老牛| 日韩男女性生活视频| 国产黄在线看| 欧美乱妇20p| 超薄肉色丝袜一二三| 久久99精品视频| 国产一级片91| 奇米777国产一区国产二区| 人体精品一二三区| yw视频在线观看| 日韩一区二区精品葵司在线 | 91精品国产乱码久久久久久久| 成人免费午夜电影| 在线午夜影院| 日韩av网站在线| 91丨九色丨海角社区| 国产精品国产三级国产aⅴ无密码| 国内自拍第二页| 伊人精品成人久久综合软件| 免费影院在线观看一区| 日本国产亚洲| 国内精品视频一区| 成人免费在线电影| 日韩欧美你懂的| 日本免费精品视频| 国产成人aaa| 777精品久无码人妻蜜桃| 日韩av免费大片| 国产精品嫩草在线观看| 日韩制服一区| 久久久久国产精品免费网站| 亚洲在线视频播放| 亚洲一区二区三区四区在线 | 亚洲三级在线免费观看| 99久久免费看精品国产一区| 美女网站在线免费欧美精品| 可以看毛片的网址| 日韩精品四区| 国产欧美亚洲日本| 婷婷精品久久久久久久久久不卡| 97视频在线观看亚洲| 在线免费黄色| 日韩av在线网站| 99久久国产免费| 在线影视一区二区三区| 久久精品免费在线| 国产精品二区一区二区aⅴ污介绍| 黄色国产在线视频| 欧美日韩免费| 91成人免费观看| 久久久成人av毛片免费观看| 久久青草精品视频免费观看| 欧洲不卡av| 亚洲视频第一页| 欧美 日韩 国产 精品| 在线播放中文字幕一区| www.欧美色| 五月婷婷激情综合| 岛国毛片在线观看| 国产精品电影院| 极品久久久久久久| www国产成人| 伊人久久一区二区三区| 国内精品不卡在线| 天天干天天玩天天操| 久久久久久婷| 干日本少妇首页| 国产一区二区三区久久| 日韩国产一级片| 欧美午夜不卡影院在线观看完整版免费| 色之综合天天综合色天天棕色| 西野翔中文久久精品国产| 官网99热精品| 北条麻妃在线一区二区免费播放 | 精品视频网站| 欧美极品一区二区| 网友自拍一区| 久久综合九九| 日韩伦理一区二区三区| 国产一区二区三区高清视频| 成人在线视频你懂的| 5g影院天天爽成人免费下载| 国产在线一区不卡| 91亚洲永久免费精品| 2019年精品视频自拍| 国产精品久久久久999| 姬川优奈av一区二区在线电影| 日本精品视频在线播放| 成人天堂yy6080亚洲高清| 欧洲成人免费视频| 亚洲天堂导航| 国产精品第10页| 日韩精品一区二区三区av| 国产精品一区二区女厕厕| 91精品国产66| 成人欧美一区二区三区黑人孕妇 | av伦理在线| 98精品国产自产在线观看| 鲁鲁在线中文| 国产成人午夜视频网址 | wwwxx欧美| 国产suv精品一区| 久久人人九九| 成人同人动漫免费观看| 欧美aaa在线观看| 欧美午夜久久| www.四虎成人| 麻豆一区二区三| 中文字幕第10页| 蜜桃av一区| 日韩av片网站| 国产精品亚洲综合久久| 男人舔女人下面高潮视频| 蜜臀久久99精品久久久画质超高清 | 一本久道久久综合狠狠爱| www日韩视频| 国产美女在线精品| 中文字幕一区二区久久人妻网站| 国产女人18水真多18精品一级做| 久久国产美女视频| 狠狠干狠狠久久| 在线黄色av网站| 精品福利一二区| 黄色在线小视频| 欧美超级免费视 在线| 小草在线视频免费播放| 国产一区二区丝袜高跟鞋图片| 日韩一区二区三区精品| 欧美精品国产精品久久久 | 成人激情自拍| 日韩女优中文字幕| 亚洲欧美综合| 黄色国产小视频| 国产a精品视频| 四虎成人免费影院| 亚洲国产成人av网| 在线免费看毛片| 亚洲精品理论电影| 国产成人高清精品| 国产v综合v亚洲欧美久久| 日韩视频一区二区三区四区| 日韩欧美一区二区三区四区五区| 中文字幕日韩欧美精品高清在线| 久章草在线视频| 成人精品国产福利| 久久人妻无码aⅴ毛片a片app| 黑人巨大精品欧美一区二区免费| 国产激情无套内精对白视频| 中文字幕精品一区久久久久| 菠萝蜜视频在线观看www入口| 国产精品中文字幕久久久| 日本久久成人网| 丁香婷婷综合激情| 久久国内精品自在自线400部| www.88av| 亚洲制服丝袜av| 97精品人妻一区二区三区| 亚洲欧美中文日韩v在线观看| 日本片在线观看| 国产专区欧美专区| 精品久久网站| 国产日产欧美视频| av电影在线观看不卡| 久久久久久久九九九九| 欧美人伦禁忌dvd放荡欲情| 国产一级在线观看| 78m国产成人精品视频| 66精品视频在线观看| 国产精品久久成人免费观看| 秋霞成人午夜伦在线观看| 无码一区二区三区在线| 欧美日韩在线第一页| 欧美一级特黄aaaaaa| 欧美精品videos另类日本| 高清久久精品| 国产免费xxx| 国产精品正在播放| 欧美国产日韩综合| 精品久久久久av影院| 污视频网站在线免费| 亚洲影院色在线观看免费| 久久精品久久久| 久久久久亚洲av片无码v| 亚洲精品国产一区二区三区四区在线| 一区二区www| 美女撒尿一区二区三区| 国产在线不卡一区二区三区| 亚洲中文字幕无码一区二区三区| 国产精品一区二区视频| 欧美高清视频一区二区三区| 精品国产99国产精品| 欧美日韩在线观看首页| 久久久久久国产精品一区| 亚洲欧美日韩在线观看a三区 | 国产米奇在线777精品观看| av成人免费网站| 日韩欧美aaaaaa| 欧美13videosex性极品| 欧美日韩高清免费| 日本欧美久久久久免费播放网| 污污视频网站在线免费观看| 欧美疯狂做受xxxx富婆| 视频在线观看入口黄最新永久免费国产 | 国产精品无码av在线播放| 2017欧美狠狠色| 日韩一区二区不卡视频| 日韩视频一区二区三区在线播放 | 欧美性视频精品| 日韩精品一页| 日本一道在线观看| 成人精品高清在线| 波多野结衣黄色| 美女少妇精品视频| 日韩美女国产精品| 超碰在线97免费| 99久久国产综合精品麻豆| 内射一区二区三区| 日韩欧美一区二区久久婷婷| 成年女人在线看片| 亚洲高清视频在线观看| 国产成人a级片| 影音先锋在线国产| 久久久久999| 一本久久青青| 男女视频在线观看网站| 懂色av一区二区三区| 午夜激情在线观看| 国语精品免费视频| 捆绑变态av一区二区三区| 国产精品99无码一区二区| 自拍偷拍免费精品| 久久99国产精品久久99大师| 在线观看av网页| 图片区小说区区亚洲影院| 午夜在线视频| 精品一卡二卡三卡四卡日本乱码| 久久97超碰色| 精品国产xxx| 久久频这里精品99香蕉|