Angular 2应用的8个主要构造块有哪些


Posted in Javascript onOctober 17, 2016

前面的话:最近空余时间在学 Angular 2,国庆节的时候看了官网的quickstart,还写了一篇文章,只是一个hello world demo。后面继续看了它的一个项目教程,刚开始还可以跟上,当后面就比较混乱了。的确,对于新手来讲,要了解一个框架还是比较麻烦的。所以停止项目,开始看看 angular 的整体框架是如何的,联系项目,分析下,慢慢来。

学习链接:中文官网

正文开始:

angular 应用:用带 angular 拓展语法的 HTML 写模板,用组件类管理这些模板,用服务添加应用逻辑,在模块中打包发布组件与服务。通过引导 根模块启动应用。 angular 在浏览器中接管、展现应用的内容,并根据我们提供的操作指令响应用户的交互。

这几个名词很重要,贯穿angular应用开发。

angular 应用的 8个主要构造块:

模块modules
组件components
模板template
元数据metadata
数据绑定data binding
指令directive
服务services
依赖注入dependency injection

模块

angular 应用是模块化的,有自己的模块系统,叫做 angular 模块/NgModules。

到底模块是什么?在angular里模块化意味着什么?

angular 应用至少有一个模块(根模块),称为 AppModule。

大多数应用都有很多其它的 特性模块,它们由一组领域类、工作流、或紧密相关的功能聚合形成。

angular的所有模块都是一个带有 @NgModule 装饰器的类。

angular的模块是类!!!

装饰器是用来修饰JavaScript类的函数。负责把元数据附加到类上。

NgModule 是一个装饰器函数,它接收一个用来描述模块属性的元数据对象。属性有:

declarations(声明):本模块中拥有的视图类。angular 有三种视图类:组件、指令、管道。
exports:declarations的子集,可用于其它模块中的组件模板。
imports:本模块组件模板中需要由其他模板导出的类。
providers:服务的创建者。本模块把它们加入全局的服务表中,让他们在应用中的任何部分都可被访问到。
bootstrap:标识出应用的主视图(根组件)。只有根模块才可设置此属性。

下面是一个简单的根模块:

// app.module.ts
import { NgModule }   from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

// @NgModle 装饰器函数,接受一个对象,对象有几个属性
@NgModule({
 imports:   [ BrowserModule ],
 providers:  [ Logger ],
 declarations: [ AppComponent ],
 exports:   [ AppComponent ],
 bootstrap:  [ AppComponent ]
})

// AppComponent 的 export 语句导出,根模块不需要导出,其他组件不需导入根模块。
export class AppModule { }

引导根模块来启动应用。在 main.ts 文件中引导 AppModule:

// app/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// 从app.module 文件导入了 AppModule
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

此时,项目只有 app/app.module.ts 文件和 app/main.ts ,前者定义了应用的根模块,后者引用它来启动应用。

Angular 模块与JavaScript模块比较:

JavaScript的模块化是分文件导入的,各文件就是各模块。

Angular 模块(用 @NgModule 装饰的类)是Angular的基础特性。

JavaScript的模块系统管理一组JavaScript对象。

在JavaScript中,每个文件就是一个模块,该文件中定义的对象从属于该模块。通过 export 关键字,可以把它的某些对象声明为公开。别的模块可以使用 import 语句访问公开对象。

JavaScript的这个特性很有用。
export 关键字声明为公开,import 语句访问公开对象。

在 Angular 里这两种都会用到,从上面的两个个文件里,可以看到。

模块库

上面所说,Angular 用到了 JavaScript模块,所以它的JS模块就是库模块,JS文件库。

Angular 库的名字都以 @angular 前缀,可以使用 npm 包管理工具安装,并如上面的 import 语句可以访问它们中的对象。

这点很好理解,Angular 本来就是依托于JS实现的单页面框架,所以它本身还是需要丰富的JS库的。
比如,从 @angular/core 库导入 Component 装饰器:

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

使用JavaScript导入语句从Angular 库中导入 Angular 的某些模块。

import { BrowserModule } from '@angular/platform-browser';

在上面根模块的代码中,应用模块需要 BrowserModule 的某些素材,所以把它加入 @NgModule 元数据的 imports 中:

imports :[ BrowserModule ];

我们看看基本的@angular库中有哪些JS模块:

common
compiler
core
forms
http
platform-browser
platform-browser-dynamic
router
upgrade

所以,我们同时使用 Angular 和 JavaScript的模块化系统。

这块的 imports 和 exports 比较混乱,可以自己梳理下。

组件

组件负责控制屏幕上的一小块地方,就是视图。

在类中定义组件的应用逻辑(被用来为视图提供支持)。组件通过一些由属性和方法组成的API与视图交互。

所以说组件是联系视图的。

前面的 export 关键字可以把模块中的类声明为公开的,然后 import 里实现访问。

类里面有许多属性和方法。

模板

通过组件自带的模板来定义视图。模板是以HTML形式存在的,它告诉 Angular 如何渲染组件(视图)。

看一个组件文件的模板:

// app/hero-list.component.html
<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<ul>
 <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
  {{hero.name}}
 </li>
</ul>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>

模板看起来就是标准 HTML,它里面有一些非标准HTML的语法。*ngFor、{{hero.name}}、{click}、[hero] 和 <hero-derail> ,它们是 Angular 的模板语法。

所以说,Angular 是通过这种方式来处理 HTML的。

元数据

元数据告诉Angular如何处理一个类。

之前 export 的类里有一些方法和属性,但是怎么处理这个类?

只要把元数据附加到这个类,就意味着这个类是个组件。

在 TypeScript 中,我们用装饰器(decorator)来附加元数据。

分析下面的元数据:

// app/hero-list.component.ts
@Component({
 moduleId: module.id,
 selector:  'hero-list',
 templateUrl: 'hero-list.component.html',
 providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

@Component装饰器把紧随其后的类标记成了组件类。

在装饰器后面的类就会被转为组件类?

装饰器里的配置项:

moduleId:为与模块相关的URL提供基地址。
这个地址怎么使用的?
selector:CSS 选择器,它告诉 Angular 在父级HTML寻找一个标签,然后创建组件实例并插入标签中。
实现HTML的显示。
templateUrl:组件HTML模板的模块相对地址。
HTML模板的设置位置。
providers:数组,包含组件所依赖的服务所需要的依赖注入提供商。告诉Angular该组件的构造函数需要服务,组件可以从服务获取数据。
某些数据的传递通过服务进行,否则,其他的视图只能控制静态的展示。

@Component 里的元数据会告诉 Angular 如何取得你为组件设定的元数据。

模板、元数据和组件共同描绘出这个视图。

组件就是视图,模板提供HTML的结构性。

数据绑定

如果没有框架,那么一些都需要我们来做。把数据值推送到HTML控件,并把用户的反馈接收转换成动作和值更新显示,你可以使用jQuery来实现这个过程。

Angular 框架实现数据绑定,一种让模板各部分与组件的各部分相互联系的机制。在模板HTML中添加绑定标记,Angular 会连接模板和组件。

意味着,我们刻意自动实现视图数据的更新,因为它绑定了组件,可以实现数据的关联。

看一个示例:

// app/hero-list.component.ts

<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>

观察到在这个模板HTML里,有一些非标准HTML的字符。

{{hero.name}} 插值表达式:在元素中显示组件的 hero.name属性的值。
[hero] 属性绑定:把父组件的值传到子组件的 hero 属性中。
(click) 事件绑定:当用户点击元素时调用方法。

文件之间的互相关系需要梳理清楚。
双向数据绑定:同时实现属性绑定和事件绑定的功能。看示例:

// app/hero-detail.component.ts

<input [(ngModel)]="hero.name">

数据属性的值会从具有属性绑定的组件传到输入框,事件绑定使用户的修改被传回组件,把属性值设为最新的值。

指令

Angular 模板是动态的。当 Angular 渲染它们时,它会根据指令对DOM进行修改。

就是说解析模板HTML的时候,会解析其中的指令。

指令是一个带有指令元数据的类。

指令是一个类,并且它含有指令源数据。

在TypeScript中,要通过 @Directive 装饰器把元数据附加到类上。

和之前的类的元数据一样,通过 @Component 装饰器把元数据附加到后面的类,编程组件类。这个就是通过 @Directive 装饰器把一些元数据附加到后面的指令类。

结构型指令:通过在DOM中添加、移除、替换元素修改布局。ngFor 、 ngIf。

属性指令:修改现有元素的外观或行为。ngModel

服务

服务分很多种,值、函数、应用所需的特性。

几乎任何东西都可以是一个服务。典型的服务是一个类。

例如:

日志服务
数据服务
消息总线
税款计算器
应用程序配置

组件是最大的服务消费者。

组件的一些操作需要服务提供一些数据。

示例,把日志记录显示到浏览器控制台:

// app/logger.service.ts

export class Logger {
 log(msg: any)  { console.log(msg); }
 error(msg: any) { console.error(msg); }
 warn(msg: any) { console.warn(msg); }
}

这些服务使得组件不用去服务器获取数据、进行验证……,这一切都可以通过服务完成。

组件的任务就是提供用户体验,仅此而已!

它介于视图(由模板渲染)和应用逻辑(包括模型)之间。

设计良好的组件为数据绑定提供属性和方法,对它们不重要的事情委托给服务。

依赖注入

依赖注入是提供类的新实例的一种方式,负责处理好类所需的全部依赖(服务)。

Angular 使用依赖注入提供我们需要的组件及组件所需的服务。

Angular 能通过查看构造函数的参数类型,来的值组件所需的服务。

示例:

// app/hero-list.component.ts

constructor(private service: HeroService) { }

构造函数的参数提到了一个服务。

当 Angular 创建组件时,会先为组件所需的服务找一个注入器(Injector)。

注入器是一个维护服务实例的容器,存放着以前创建的实例。如果容器中还没有所请求的服务实例,注入器就会创建一个服务实例,并且添加到容器中,然后把这个服务返回给 Angular。当所有服务都被解析完并返回, Angular 会以这些服务为参数去调用组件的构造函数,这就是依赖注入。

也就是说服务是先于组件被执行的。它先处理所有的服务到一个仓库,然后再处理组件,组件需要哪个服务就从仓库取出来给你。
提供商添加到根模块,在任何地方使用的都是服务的同一个实例:

// app/app.module.ts

providers: [
 BackendService,
 HeroService,
 Logger
],

提供商是确定处理组件之前必须存在所依赖的组件
也可以把它注册到组件层:

// app/hero-list.component.ts

@Component({
 moduleId: module.id,
 selector:  'hero-list',
 templateUrl: 'hero-list.component.html',
 providers: [ HeroService ]
})

添加到装饰器元数据的属性中。

依赖注入的要点:

1、依赖注入渗透在整个Angular框架中
2、注入器是机制的核心
      注入器负责维护一个容器,存放创建过的服务实例
      注入器能使用提供商创建一个新的服务实例
3、提供商是一个用于创建服务的配方。
4、把提供商注册到注入器。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
validator验证控件使用代码
Nov 23 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
Oct 23 Javascript
用json方式实现在 js 中建立一个map
May 02 Javascript
js实现按钮控制图片360度翻转特效的方法
Feb 17 Javascript
jQuery实现的感应鼠标悬停图片色彩渐显效果
Mar 03 Javascript
JavaScript实现将xml转换成html table表格的方法
Apr 17 Javascript
javascript父子页面通讯实例详解
Jul 17 Javascript
jQuery3.0中的buildFragment私有函数详解
Aug 16 Javascript
JS实现的简单拖拽购物车功能示例【附源码下载】
Jan 03 Javascript
基于jQuery实现Ajax验证用户名是否可用实例
Mar 25 jQuery
Laravel 如何在blade文件中使用Vue组件的示例代码
Jun 28 Javascript
js面向对象编程OOP及函数式编程FP区别
Jul 07 Javascript
jQuery表单验证简单示例
Oct 17 #Javascript
jQuery右下角悬浮广告实例
Oct 17 #Javascript
WEB前端实现裁剪上传图片功能
Oct 17 #Javascript
Javascript获取background属性中url的值
Oct 17 #Javascript
JS+HTML5实现的前端购物车功能插件实例【附demo源码下载】
Oct 17 #Javascript
jquery checkbox的相关操作总结
Oct 17 #Javascript
JS动态添加选项案例分析
Oct 17 #Javascript
You might like
SONY SRF-22W(33W)的电路分析和维修案例
2021/03/02 无线电
php下正则来匹配dede模板标签的代码
2010/08/21 PHP
php全排列递归算法代码
2012/10/09 PHP
ThinkPHP中使用ajax接收json数据的方法
2014/12/18 PHP
php中异常处理方法小结
2015/01/09 PHP
php浏览历史记录的方法
2015/03/10 PHP
PHP设计模式之适配器模式代码实例
2015/05/11 PHP
js函数中onmousedown和onclick的区别和联系探讨
2013/05/19 Javascript
jquery 操作两个select实现值之间的互相传递
2014/03/07 Javascript
JSONP跨域GET请求解决Ajax跨域访问问题
2014/12/31 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
Bootstrap每天必学之表格
2015/11/23 Javascript
分享自己用JS做的扫雷小游戏
2016/02/17 Javascript
jQuery html表格排序插件tablesorter使用方法详解
2017/02/10 Javascript
实例解析js中try、catch、finally的执行规则
2017/02/24 Javascript
如何在vue里添加好看的lottie动画
2018/08/02 Javascript
使用angular-cli webpack创建多个包的方法
2018/10/16 Javascript
你不知道的 TypeScript 高级类型(小结)
2020/08/28 Javascript
[45:17]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第三场 1月9日
2021/03/11 DOTA
linux系统使用python获取cpu信息脚本分享
2014/01/15 Python
简单介绍Python中的filter和lambda函数的使用
2015/04/07 Python
python 读取文本文件的行数据,文件.splitlines()的方法
2018/07/12 Python
python实现Zabbix-API监控
2018/09/17 Python
python数据结构之线性表的顺序存储结构
2018/09/28 Python
ERLANG和PYTHON互通实现过程详解
2019/07/05 Python
python标准库OS模块详解
2020/03/10 Python
pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]
2020/04/24 Python
python 使用elasticsearch 实现翻页的三种方式
2020/07/31 Python
Python 可视化神器Plotly详解
2020/12/26 Python
matplotlib实现数据实时刷新的示例代码
2021/01/05 Python
蒙蒂塞罗商店:Monticello Shop
2018/11/25 全球购物
中班开学寄语
2014/04/04 职场文书
2014年党支部书记工作总结
2014/12/04 职场文书
物业接待员岗位职责
2015/04/15 职场文书
安全承诺书格式范本
2015/04/28 职场文书
如何写辞职信
2015/05/13 职场文书