Angular从零到一3.2 让待办事项变得有意义-阿里云开发者社区

开发者社区> 华章出版社> 正文

Angular从零到一3.2 让待办事项变得有意义

简介:

3.2 让待办事项变得有意义


我们希望的Todo页面应该有一个输入待办事项的输入框和一个显示待办事项状态的列表。那么我们先来定义一下Todo的结构,Todo应该有一个id用来唯一标识,还应该有一个desc用来描述这个Todo是干什么的,再有一个completed用来标识是否已经完成。下面建立这个Todo模型,在todo文件夹下新建一个文件todo.model.ts:

export class Todo {

  id: number;

  desc: string;

  completed: boolean;

}

然后我们应该改造一下Todo组件了,引入刚刚建立好的Todo对象,并且建立一个todos数组作为所有Todo的集合,一个desc是当前添加的新的Todo的内容。当然,我们还需要一个addTodo方法把新的Todo加到todos数组中。这里我们暂且写一个漏洞百出的版本:

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

import { Todo } from './todo.model';

 

@Component({

  selector: 'app-todo',

  templateUrl: './todo.component.html',

  styleUrls: ['./todo.component.css']

})

export class TodoComponent implements OnInit {

  todos: Todo[] = [];

  desc = '';

  constructor() { }

 

  ngOnInit() {

  }

 

  addTodo(){

    this.todos.push({id: 1, desc: this.desc, completed: false});

    this.desc = '';

  }

}

然后我们改造一下src\app\todo\todo.component.html:

<div>

  <input type="text" [(ngModel)]="desc" (keyup.enter)="addTodo()">

  <ul>

    <li *ngFor="let todo of todos">{{ todo.desc }}</li>

  </ul>

</div>

如上述代码所示,我们建立了一个文本输入框,这个输入框的值应该是新Todo的描述(desc),我们想在用户按了回车键后进行添加操作((keyup.enter)="addTodo())。因为todos是个数组,所以我们利用一个循环将数组内容显示出来(<li *ngFor="let todo of todos">{{ todo.desc }}</li>)。好了,让我们欣赏一下成果吧,如图 3.3所示。

 

图 3.3 有实际意义的Todo

隔离业务逻辑

如果我们还记得之前提到的业务逻辑应该放在单独的service中,我们还可以做得更好一些。在todo文件夹内建立TodoService:ng g s todo\todo。上面的例子中所有创建的todo都是id为1的,这显然是一个大bug,我们看一下怎么处理。常见的不重复id创建方式有两种,一个是采用一个自增长数列,另一个是采用随机生成的一组不可能重复的字符序列,常见的就是UUID。

我们来引入一个uuid的包:npm install --save angular2-uuid,由于这个包中已经含有了用于typescript的定义文件,因此这里执行这一个命令就足够了。这里稍微提一下如何引入第三方JavaScript类库,分几种情况:

如果类库的npm包中含有类型定义文件(查看node_modules/第三方类库 中是否有 .d.ts 后缀的文件),那么直接使用“npm install --save 要引入包的名称”即可。

如果类库中没有类型定义文件,可先使用“npm i --save 要引入包的名称”正常安装,然后执行“npm install @types/要引入包的名称--save-dev”。这个命令要在 @types/中搜索安装类型定义文件。

当然,还是有可能找不到类型定义文件,这时还是可以使用的,但需要手动添加类型定义:首先在 src/typings.d.ts 中写 declare module'要引入包的名';,然后在组件中可以这样引入 import * as friendName from'要引入包的名';(friendName是个友好别名,起一个你认为符合你风格的名称就行),使用时就可以这样调用方法了:

friendName.method();

由于此时Todo对象的id已经是字符类型了,因此请更改其声明为id: string;。 然后修改service成下面的样子:

import { Injectable } from '@angular/core';

import { Todo } from './todo.model';

import { UUID } from 'angular2-uuid';

 

@Injectable()

export class TodoService {

 

  todos: Todo[] = [];

 

  constructor() { }

 

  addTodo(todoItem:string): Todo[] {

    let todo = {

      id: UUID.UUID(),

      desc: todoItem,

      completed: false

    };

    this.todos.push(todo);

    return this.todos;

  }

}

当然,我们还要把组件中的代码改成使用service的:

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

import { TodoService } from './todo.service';

import { Todo } from './todo.model';

 

@Component({

  selector:'app-todo',

  templateUrl: './todo.component.html',

  styleUrls: ['./todo.component.css']

  providers:[TodoService]

})

export class TodoComponent implements OnInit {

  todos: Todo[] = [];

  desc: string = '';

  constructor(private service:TodoService) { }

 

  ngOnInit() {

  }

 

  addTodo(){

    this.todos = this.service.addTodo(this.desc);

    this.desc = '';

  }

}

为了可以清晰地看到我们的成果,我们为Chrome浏览器装一个插件,在Chrome浏览器的地址栏中输入chrome://extensions,拉到最底部会看到一个“获取更多扩展程序”的链接,点击这个链接然后搜索“Augury”,安装即可。安装好后,按F12键调出开发者工具,里面出现一个叫“Augury”的tab,如图 3.4所示。

 

图3.4 Augury可以是一个专门针对Angular的Chrome插件

我们可以看到id这时候被设置成了一串字符,这个就是UUID了。

版权声明:如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:developerteam@list.alibaba-inc.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接