Angular学习笔记(2)——TODO小应用

2017-01-10 08:18:20来源:cnblogs.com作者:学数学的程序猿人点击

# Angular学习笔记(2)——TODO小应用## 1. 写在前面之前我们跑了Angular的[Hello World](http://www.cnblogs.com/dongkuo/p/6259637.html),你是不是对它有点感觉了呢?这一篇将结合一个**TODO**程序来继续学习Angular的用法。梳理一下之前的Hello World程序。我们写了一个`main.ts`来引导模块`AppModule`,而该模块又包含组件`AppComponent`,这是一个Angular应用最基本的结构。下面再来简单地看看Angular各部件的含义。先看**Module(模块)**。Angular应用是模块化的,每一个Angular应用至少有一个模块,被称为根模块,通常我们会以`AppModule`来命名。要想定义一个模块类,只需要在类上加上`@NgModule`装饰器。`@NgModule`还接收一个元数据对象,该对象有如下几个重要的属性,其中前3个在**Hello World**中已经见到过:> 1. `declarations`: 声明本模块中拥有的视图类。 Angular 有三种视图类:组件、指令和管道。2. `bootstrap`: 指定应用的主视图(称为根组件),它是所有其它视图的宿主。只有根模块才能设置bootstrap属性。3. `imports`: 导入其他模板类。4. `exports`: 导出本模块的视图类。5. `providers`: 服务的创建者,并加入到全局服务列表中,可用于应用任何部分。接下来是**Component(组件)**。组件是负责控制UI上一小块区域的部件,比如一个用户列表,一个标题栏等,我们把这一小块区域称之为**视图**。要想定义一个组件,我们只需要在组件类的上面添加`@Component`装饰器,装饰器接受的元数据包含视图的名字(`selector`),视图的模板(`template`或`templateUrl`),视图的样式(`styleUrls`)等属性。而在组件类里面,我们会定义一些与视图相关的属性和视图的逻辑操作。以上的两个概念**Module**和**Component**我们在Hello World中都有些体会,在接下来的**TODO**例子中会介绍**模板语法**,主要介绍**数据绑定**,它的意思就是将变量视图绑定起来,这么做的好处就是一旦变量发生变化或者视图发生变化,它们都会“同步更新”对方(双向数据绑定)。## 2. TODO应用好了,不码概念了,概念听得越多越糊涂。还是来看实际的例子比较靠谱。点击[这里](http://derker.cn/demo/angular-todo/index.html)查看演示效果。这次我们不自己手动建工程了,采用另一种方式:使用`git`克隆Angular的**quickstart**项目,在此之上进行开发。使用如下命令进行克隆:```git clone https://github.com/angular/quickstart angular-todo```用**idea**或其他IDE打开`angular-todo`工程,在从命令行输入`npm install`安装依赖库。接着运行`npm start`,官方的Hello World就跑起来了,我们几乎不用修改它写好的代码(`app.module.ts`除外),只需在上面添加代码即可。采用Angular模块化的思维去分析**TODO**应用,由于功能很简单,我们没必要建立新的模块,只需要建立一个**TODO**组件即可,页面分为如下形式:![](http://ojapxw8c8.bkt.clouddn.com/%E9%80%89%E5%8C%BA_006.png) 下面来实现`TodoComponent`。首先是新建`todo.component.ts`、`todo.component.html`、`todo.component.css`三个文件。然后在`todo.component.ts`定义出`TodoComponent`,并指定模板(通过`templateUrl`属性)和样式(通过`styleUrls`属性):```import {Component} from '@angular/core';@Component({ moduleId: module.id, selector: 'todo', templateUrl: 'todo.component.html', styleUrls: ['todo.component.css']})export class TodoComponent {}```以上和Hello World中的代码没有多少区别,相信很容易看懂。Todo组件先写到这,我们现在将它声明到`AppModule`中:```import {NgModule} from '@angular/core';import {BrowserModule} from '@angular/platform-browser';import { FormsModule } from '@angular/forms';import {AppComponent} from './app.component';import {TodoComponent} from './todo.component';@NgModule({ imports: [BrowserModule, FormsModule], declarations: [AppComponent, TodoComponent], bootstrap: [AppComponent]})export class AppModule {}```注意,以上还引入了官方的`FormsModule`模块,它用于form元素的相关操作,我们待会会用到,这里提前引入。现在,我们就可以在`AppComponent`中使用自定义的todo组件了。和之前分析的结构一样,模板中先是一个标题,再是todo组件,然后添加点样式:```import {Component} from '@angular/core';@Component({ selector: 'my-app', template: `

TODO

`, styles:[`.main-container{width: 960px; margin: 0 auto;}`]})export class AppComponent {}```现在基本的骨架就OK了,接下来的重点就是todo组件的具体编写了。之前有提过,使用Angular等数据驱动的框架和写jQuery等库最大的不同在于Angular是以数据为中心,任何变化的视图(或者不变的视图,只要你愿意)背后必然对应着相应的数据结构。拿我们的todo应用来说,视图中的todo列表的背后就对应着一个数组,todo列表的每一项就对应数组中的某一个位置上的元素。如果我们想添加或删除todo列表项,那么只需要对对应的数组进行添加或删除操作;如果我们想修改todo列表的某一项的信息,我们只需要修改对应的数组的对应位置上的todo对象即可。要知道,我们用JS修改一个变量,要比直接修改DOM轻松的多。如果你是第一次使用Angular这类采用数据驱动的框架,你一定会觉得It's amazing,妈妈再也不用担心我拼接html字符串了。有了上面的分析,我们先要将一个todo项的数据结构定义出来,因此在`todo.component.ts`中,添加如下代码:```class Item { content: string; // todo内容 date: Date; // todo创建日期 done: boolean; // 是否完成 constructor(content: string) { this.content = content; this.date = new Date(); }}```然后在`TodoComponent`类中,我们需要定义一个`Item`数组,表示我们的todo列表,并且我们还要需要一个添加todo项的方法:```export class TodoComponent { todoList: Item[] = []; addTodo(value: any): void { this.todoList.push(new Item(value)); }}```OK,TodoComponent类暂时就完成了,代码很简单,就不做说明了。接下来就是todo组件模板和样式的编写。模板代码其实和我们平常写的html代码差不多,不同之处在于加了一些Angular自定义的语法,用于控制页面的渲染,模板代码如下:```

    Empty...

```要重点说说上面的**模板语法**。首先最先让你困惑的是这句,```````#input`是什么鬼?其实它的官方叫法是**template reference variable(模板引用变量)**,它用于**在模板中对DOM元素或指令的引用**。这里`#input`就是用`input`变量来引用它所在的input元素(`即`),因此在后面`(keyup.enter)="addTodo(input.value)"`中,我们可以用`input.value`拿到输入框输入的值。那么`keyup.enter`又是什么鬼呢?它其实被称为**Event binding(事件绑定)**。为了说清楚事件绑定的概念,我们把它拆开来看,一个是事件,一个是绑定。先说事件。这和原生js一样,比如鼠标点击(click),上面的按键后松开(keyup)等,都是事件。并且Angular还能自定义事件,这个先不做说明。上面的`keyup.enter`事件会在键盘`enter`键抬起时触发,触发后会调用我们在`TodoComponent`中写好的addTodo方法,并把`input.value`作为参数传递进去。再说绑定。之前已经多次提到过,绑定实际上就是把数据与视图,事件与方法等关联起来,一方发生变化或被触发,另一方自动地随之做出变化或被触发。绑定是有方向的,这个方向指的是数据流动的方向,因此可分为如下三类:![](http://ojapxw8c8.bkt.clouddn.com/%E9%80%89%E5%8C%BA_008.png) 这三类绑定方式的语法分别是`[]`,`()`,`[()]`:```// 第一种,数据源 -> 视图// 第二种,视图 -> 数据源// 第三种,视图 <-> 数据源```在todo组件的模板代码中,我们还用到了两个指令`*ngIf`和`*ngFor`,它们是Angular的**内置指令**,用法根据上面的例子应该就能看懂。最后还有一个语法是**管道**,操作符是:”|”,这个跟其他框架中所谓的“过滤器”的概念很像。它将操作符左侧的表达式的值作为右侧函数的输入,最终整个表达式的值由右侧函数的返回值决定。管道还能串联。以上就是模板的基本语法,只是简单的说明,具体请参考[文档](https://angular.cn/docs/ts/latest/guide/template-syntax.html)。这样todo组件的模板就写好了,最后我们可以在`todo.component.css`中加些样式。比如:```.hint{ color: #999999;}.done{ text-decoration: line-through;}li{ line-height: 2;}```以上便是整个TODO应用的编写过程,你跑出来了吗?目前程序还有一个小缺陷,就是我们回车,输入的内容被加入todo列表后,输入框应该被清空,这个就交给你去完成了。

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台