4

问题描述

本文带领大家通过一个我自己编写的豆瓣电影的小例子认识Angular

clipboard.png

时代在发展,技术在进步。

为了规避AngularJS的一些问题,我们打开了Angular的大门。

clipboard.png

思想

随着框架的发展,涌现出了越来越多的开发思想。

从原生JS操作DOM,到JQuery简化DOM操作,到AngularJS面向数据开发,再到如今的Angular的组件化开发。

源于指令

AngularJS的核心就是指令,ng-appng-controller,哪怕一个最简单的AngularJS应用也用到了指令。

Angular随着现在组件化开发思想的流行,借鉴了现有框架的优点,可谓优秀。

下图为一个Angular标准组件的Demo,这很像AngularJS的指令,但是AngularJS的指令嵌套时需要考虑许多复杂的关系,这就使得指令的用武之地大大缩水。

Angular发现了这个问题,所以组件,是一种易于嵌套的指令。

clipboard.png

架构设计

clipboard.png

因为项目比较小,所以架构设计的也比较简单。

component:存放组件。
model:存放数据模型。
pipe:存放管道(过滤器)。
service:存放服务。

实战

环境

UI框架采用Angular MaterialBootstrap,这里用Bootstrap的原因主要是因为Material的布局比较难,研究了一下午也没研究明白怎么随心所欲的运用,最后还是引了个Bootstrap

如果你在Material方面造诣比较深的话,用这个就够了,只是笔者初学,还不能灵活的运用Material

clipboard.png

模型

clipboard.png

我们先从模型model说起,各位开发者对于前台是否应该建实体的观点莫衷一是,这里,我阐述下我自己的观点。

clipboard.png

前台有了实体之后,可以对请求时返回的观察者Observable对象进行类型声明,这样可以让代码更清晰,同时有了实体之后,在TypeScript中的各种操作都有代码提示,我们再也不需要去控制台console.log看看这个返回的对象都有些什么属性了,有IDE为我们进行类型检查,编码时不易出错。

就像Android一样,对于服务器而言,也是一个前端,也需要建实体,然后转换为相应的数据类型。既然TypeScript也正在往这方面靠拢,那我们何乐而不为呢?

服务

clipboard.png

clipboard.png

看下面的代码,我们不需要再去像AngularJS一样链式调用then然后再去successerror了。

Angular中结合rxjs,对于异步有一个新的处理方式----观察者模式。

clipboard.png

RxJS: 用于JavaScript的响应式拓展库。RxJS是一个使用观察者模式让异步和基于回调的代码更加容易的响应式编程库。

HttpClient的请求方法返回的是一个可观察的对象,我们可以订阅这个对象,当发生事件时执行我们的方法,其实也就是回调函数与观察者模式的结合。

组件

这是笔者在项目中编写的几个组件。

clipboard.png

index.html中使用默认创建的app-root组件作为应用的起始。

clipboard.png

然后app-root中还有组件,这就是一个组件树,Angular就从app-root这个根节点开始渲染该组件树上的各个组件。

组件化开发,我们的项目结构会更清晰,同时每个组件的职责更明确。

clipboard.png

生命周期

条条大路通罗马,无论一个框架如何设计,它的本质还是没有变的。

和微信小程序中的组件一样,Angular的组件也是有生命周期的。

官方文档展示了一个组件从创建到消亡的各种钩子,这些钩子是有时间顺序的。

clipboard.png

想要在组件不同的生命周期执行自定义的方法,只需要在组件类中实现相应的接口即可。

clipboard.png

还有一个问题就是第一次见Angular组件的代码时不知道初始化是放在constructor里还是ngOnInit里,到了现在也算是有了一些自己的理解。

这个就像在Spring中使用依赖注入,有时我们会在构造函数中声明要注入的对象,这里的constructorngOnInit的关系就像Spring中的构造函数@PostConstruct的关系一样,一个用于构造,一个用于初始化。

所以应该将依赖注入相关的代码声明在constructor中,初始化方法放在ngOnInit中。

输入输出

clipboard.png

去看文档,使用已有组件会有InputOutput代表的输入输出,@Input标注的属性表示该类型需要外部输入,文档中会给出类型。

Output标注的属性一般是该组件触发的某些事件,使用EventEmitter实现自定义事件,调用emit方法来发布事件。因为我编写的组件功能都比较简单,只有输入,输出的属性我们以后讨论。

管道

管道,也就是我们常说的过滤器,就是一个方法的输入什么,处理完再输出,Angular中命名为Pipe

电影的类型、导演、主演都是拿管道过滤出来的。

clipboard.png

这是过滤导演的管道源码:

clipboard.png

因为编码的时候只考虑了部分功能,没有对管道有一个整体的认识。

在现在写博客时恍然大悟,这样写,仅仅只能过滤Director数组,但是我这个方法呢?我这个源码可不仅仅是过滤Director数组,只要是数组,并且该数组中的对象有name属性,都可以按规则过滤。

所以接口的价值就体现出来了:

clipboard.png

路由

clipboard.png

路由用着和之前的ui-router感觉差不多,不同的路由,就往router-outlet里嵌套不同的内容。

clipboard.png

总结

TypeScript写着挺爽的,尤其是箭头函数,再也不用去写function关键字了。

类型检查做得很优秀,不必像我们以往在JavaScript中写了一个方法,然后去写注释,我的输入应该是个什么类型,对象应该有什么属性,然后可能别人还看不懂。建个接口,清晰简洁,传错了编译器还会提示。


张喜硕
2.1k 声望423 粉丝

浅梦辄止,书墨未浓。