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 相关文章推荐
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
Aug 13 Javascript
javascript判断非数字的简单例子
Jul 18 Javascript
JavaScript实现的encode64加密算法实例分析
Apr 15 Javascript
js贪吃蛇网页版游戏特效代码分享(挑战十关)
Aug 24 Javascript
微信小程序 图片边框解决方法
Jan 16 Javascript
基于vue实现swipe轮播组件实例代码
May 24 Javascript
js统计页面上每个标签的数量实例代码
May 29 Javascript
vue中使用input[type=&quot;file&quot;]实现文件上传功能
Sep 10 Javascript
Vue实现简易翻页效果源码分享
Nov 08 Javascript
vue项目设置scrollTop不起作用(总结)
Dec 21 Javascript
微信小程序非跳转式组件授权登录的方法示例
May 22 Javascript
vue.js 2.0实现简单分页效果
Jul 29 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
让这部DC动画新作刷新你的认知
2020/03/03 欧美动漫
php递归获取目录内文件(包含子目录)封装类分享
2013/12/25 PHP
Laravel学习教程之View模块详解
2017/09/18 PHP
用JavaScript实现仿Windows关机效果
2007/03/10 Javascript
javascript 无提示关闭窗口脚本
2009/08/17 Javascript
用js做一个小游戏平台 (一)
2009/12/29 Javascript
JS 图片缩放效果代码
2010/06/09 Javascript
jquery 多行滚动代码(附详细解释)
2010/06/17 Javascript
jQuery实现当按下回车键时绑定点击事件
2014/01/28 Javascript
AngularJS的一些基本样式初窥
2015/07/27 Javascript
Bootstrap每天必学之媒体对象
2015/11/30 Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
2015/11/30 Javascript
jQuery轻松实现表格的隔行变色和点击行变色的实例代码
2016/05/09 Javascript
解决wx.onMenuShareTimeline出现的问题
2016/08/16 Javascript
javascript 中的继承实例详解
2017/05/05 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
vue实现仿淘宝结账页面实例代码
2017/11/08 Javascript
Layui 设置select下拉框自动选中某项的方法
2018/08/14 Javascript
微信小程序利用swiper+css实现购物车商品删除功能
2019/03/06 Javascript
使用VueRouter的addRoutes方法实现动态添加用户的权限路由
2019/06/03 Javascript
ES6的异步操作之promise用法和async函数的具体使用
2019/12/06 Javascript
使用js原生实现年份轮播选择效果实例
2021/01/12 Javascript
利用Python的Django框架生成PDF文件的教程
2015/07/22 Python
python学习笔记--将python源文件打包成exe文件(pyinstaller)
2018/05/26 Python
django从后台返回html代码的实例
2020/03/11 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
Pandas之缺失数据的实现
2021/01/06 Python
瑞典的玛丽小姐:Miss Mary of Sweden
2019/02/13 全球购物
绢花、人造花和人造花卉:BLOOM
2019/08/07 全球购物
安全生产计划书
2014/05/04 职场文书
保护环境倡议书500字
2014/05/19 职场文书
2019年家电促销广告语集锦
2019/10/21 职场文书
pytorch model.cuda()花费时间很长的解决
2021/06/01 Python
css filter和getUserMedia的联合使用
2022/02/24 HTML / CSS
python opencv将多个图放在一个窗口的实例详解
2022/02/28 Python
 Python 中 logging 模块使用详情
2022/03/03 Python