项目需要,要开始熟悉Angular,Hello, the world of ng!
昨天开始上手Angular,不得不说,官方文档给我的第一印象就是傻瓜式教学——基本上有着一套流程体系,跟着做即可。
第一个Demo是在StackBiltz上建立起来的,感觉像是官方给了一个半成品的玩具,让用户自行跟着教程体验,这样的入手方式还是蛮有趣的。
昨天的内容包括两块:通过demo体验ng+了解ng基本概念。
我觉得先上手一个demo,比较有助于具象认识,特别是后来看到ng的概念,才明白这样做真是太对了——ng的概念太多。不过真的要讲述对ng的认识,还是从概念出发吧:
- ng用Typescript写成的。我类比这句话,就是.NET用C#写成的。二者都是框架,我对框架的理解,就是外卖火锅店——火锅店提供了各种封装好的食材,调料包,还有汤底,这些我们自己准备可不可以呢?可以,但是很麻烦,调料要配置、汤底要熬、每样食材要买还要处理。可是如果有一家供应链比较好的火锅店,我们就可以根据自己的需要配置自己的火锅:清汤、牛油、鸳鸯、红油、麻辣.....
- ng的基本构造是模块(Module)。类比来看,就是.NET的基本构造就是窗体(Winform)。看模块的体现更容易,模块位于一个名叫.ts(ts就是TypeScript的首字母)的文件中,是窗体是位于一个.cs(cs就是CSharp的首字母)的文件中。ng 的根模块(即一个ng应用在创建时都具备的文件)是app.module.ts,.NET的根”窗体“是无法显示的,一般命名为program.cs。官方对模块的说明是,模块提供了组件(Component)的编译环境(NgModules provide a compilation context for components),同样地,一个窗体也为你放控件(Controller)提供了编译的环境。模块之间好像窗体之间可以双向传递数据,然后不同的模块可以搭建成一个程序。理解起来就是模块是一个锅,然后这个锅为你放食材提供了一个空间,这锅可以一个吃,也可以多个吃(鸳鸯、四宫格、九宫格)。
- 组件(Component)。官方对组件的定义是组件控制屏幕上被称为视图的一小片区域(A component controls a patch of screen called a view)。讲道理,这么说话,等于白说,太抽象了。要我看,组件就是是.NET中的控件。从控件的角度翻译官方对组件的定义就是,控件占据窗体的一块区域、这块区域(在ng里面)被称为视图(View)。所以先说说视图,官方原话是组件定义视图(Components define views),而这句话的正确打开方式应该是,(用控件做比方),窗体中划拨了一片区域给控件,让控件显示出来——为什么这么说呢,.NET中每个窗体文件(.cs)都有自己对应的”视图“(.design.cs)文件(根”窗体“除外),在”视图“文件中,定义了每个控件的位置、大小、属性等等。这里还要谈谈一个理解,每个非根”窗体“都是一个控件,同样地也会发现,每个非根模块都是一个组件。——这一点从ng官方提供地demo中关于组件的说明就可以看出。还找到官方的一句话:在MVC模式中,组件扮演着控制器或视图模型的角色,模板则扮演视图的角色(the component plays the part of the controller/viewmodel, and the template represents the view.)。
- 模板(Template)。这个概念我不太确定,我认为模板应该类似于组件的属性+函数。官方说是,模板定义了视图,而组件类是通过元数据(Metadata)与模板连接的。所以要理解模板,似乎要先搞懂元数据。但是这个概念巨抽象,只能看一下代码:
@Component({ selector: 'app-hero-list', templateUrl: './hero-list.component.html', providers: [ HeroService ] }) export class HeroListComponent implements OnInit { /* . . . */ }
由代码可见,元数据可能就是每个控件的构造函数(看demo中关于组件的输入以及输出可能这样的感觉会更形象写)。通过构造函数,一个控件被实例化,具备控件类的所有属性以及函数,控件的属性会被写进窗体的”视图“文件中显示出来、控件的函数也会控制控件的形式在窗体中显示出来。因此,我才有如上的类比。再看官方给出的图,更能说明我的猜想:组件创建后,传属性值给模板中的属性(属性绑定,property binding);模板将事件实例化传给组件(事件绑定,event binding)。只是在ng中,模块最终显示(模板控制)将有HTML元素展示出来。
- 管道(Pipes)。这个概念真是fancy。点开API,找到一个管道解释后,就发现原理了。
DecimalPipe:把数字转换成字符串, 根据本地化规则进行格式化,这些规则会决定分组大小和分组分隔符、小数点字符以及其它与本地化环境有关的配置项。
所以说,管道类似是.NET中的Convertor类,或者再广义地理解,管道是一切格式转换封装地API。
- 指令(Directive)。ng的指令包括结构型指令(添加、移除或替换 DOM 元素来修改布局)以及属性型指令(修改现有元素的外观或行为)。我觉得定义就是用另一个抽象的表达来解释一个抽象的表达。官方文档给出的代码例子更易懂:
- 结构型指令,其实就是一个循环语句+判断语句,如果这样再去理解结构型指令的定义,可以认为,就是控制+逻辑语句。
<li *ngFor="let hero of heroes"></li> <app-hero-detail *ngIf="selectedHero"></app-hero-detail>
- 属性型指令,可以认为就是赋值语句。
<input [(ngModel)]="hero.name">
- 结构型指令,其实就是一个循环语句+判断语句,如果这样再去理解结构型指令的定义,可以认为,就是控制+逻辑语句。
- 服务(Service)。官方给出了服务概念的广义以及狭义的定义。
- 广义上看,它包括应用所需的任何值、函数或特性。
- 狭义上看,是一个明确定义了用途的类。狭义定义似乎更能说明服务的性质,就是一个外部类。
export class Logger { log(msg: any) { console.log(msg); } error(msg: any) { console.error(msg); } warn(msg: any) { console.warn(msg); } }
这是一个把日志记录到浏览器的控制台的类。从代码里面可以很清晰地看到关键字(我也不知道在ng里是不是这个说法)class。
下面总结一下第一天学习后,对ng各个概念的理解,用.NET 框架去理解:
Angular | .NET Framework | 框架提供了便捷的开发工具 |
Typescript | C# | |
模块(Module)(.ts) | 窗体(Winform)(.cs) | 模块就是一个容器、提供了组件的编译环境 |
视图(View) | 设计文件(.design.cs) | 视图就是模块的显示体现,具体内容由组件控制 |
组件(Component) | 控件(Controller) | 组件就是基本的内容单元 |
元数据(Metadata) | 构造函数 | 元数据实例化组件,使之与模板关联 |
模板(Template) | 控件的属性以及函数 | 模板包括事件以及函数,可以通过双向绑定控制视图 |
指令(Directive) | 控制、逻辑以及赋值语句 | |
服务(Service) | 外部类 | |
管道(Pipe) | Convertor |