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 相关文章推荐
JavaScript 空位补零实现代码
Feb 26 Javascript
javascript函数以及基础写法100多条实用整理
Jan 13 Javascript
原生javascript和jquery判断浏览器版本等信息
Jul 04 Javascript
禁止空格提交表单的js代码
Nov 17 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
Jan 31 Javascript
Vue2.0组件间数据传递示例
Mar 07 Javascript
JavaScript中的普通函数和箭头函数的区别和用法详解
Mar 21 Javascript
微信小程序 本地数据存储实例详解
Apr 13 Javascript
ES6学习教程之对象的扩展详解
May 02 Javascript
vue-prop父组件向子组件进行传值的方法
Mar 01 Javascript
Vue引入jquery实现平滑滚动到指定位置
May 09 jQuery
浅谈Webpack下多环境配置的思路
Jun 27 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
山进SANGEAN ATS-909X电路分析
2021/03/02 无线电
PHP入门速成教程
2007/03/19 PHP
php比较两个绝对时间的大小
2014/01/31 PHP
php 判断字符串编码是utf-8 或gb2312实例
2016/11/01 PHP
让ThinkPHP的模板引擎达到最佳效率的方法详解
2017/03/14 PHP
Laravel框架实现的上传图片到七牛功能详解
2019/09/06 PHP
ThinkPHP6.0如何利用自定义验证规则规范的实现登陆
2020/12/16 PHP
运用Windows XP附带的Msicuu.exe、Msizap.exe来彻底卸载顽固程序
2007/04/21 Javascript
控制文字内容的显示与隐藏示例
2014/06/11 Javascript
使用Jasmine和Karma对AngularJS页面程序进行测试
2016/03/05 Javascript
vue-router路由简单案例介绍
2017/02/21 Javascript
js实现放大镜特效
2017/05/18 Javascript
JavaScript表单验证实现代码
2017/05/22 Javascript
vue使用vue-cli快速创建工程
2017/07/28 Javascript
bootstrap modal+gridview实现弹出框效果
2017/08/15 Javascript
import与export在node.js中的使用详解
2017/09/28 Javascript
Angular弹出模态框的两种方式
2017/10/19 Javascript
微信小程序使用Promise简化回调
2018/02/06 Javascript
vue组件与复用详解
2018/04/08 Javascript
webpack里使用jquery.mCustomScrollbar插件的方法
2018/05/30 jQuery
通过JavaScript下载文件到本地的方法(单文件)
2019/03/17 Javascript
[57:37]EG vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python线程、进程和协程详解
2016/07/19 Python
解决python使用open打开文件中文乱码的问题
2017/12/29 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
python动态进度条的实现代码
2019/07/03 Python
python文件读写代码实例
2019/10/21 Python
Python pexpect模块及shell脚本except原理解析
2020/08/03 Python
Python 中的函数装饰器和闭包详解
2021/02/06 Python
高中生家长会演讲稿
2014/01/14 职场文书
暑期学习心得体会
2014/09/02 职场文书
先进党支部事迹材料
2014/12/24 职场文书
创业计划书之养殖业
2019/10/11 职场文书
Html5通过数据流方式播放视频的实现
2021/04/27 HTML / CSS
Nginx的gzip相关介绍
2022/05/11 Servers
cypress测试本地web应用
2022/06/01 Javascript