详解Angular的8个主要构造块


Posted in Javascript onJune 20, 2017

Angular 主要分为八大构造块(也就是八个核心概念):模块 (module)、组件 (component)、模板 (template)、元数据 (metadata)、数据绑定 (data binding)、指令 (directive)、服务 (service)、依赖注入 (dependency injection)。其中,最核心的一个概念就就组件。

1. 模块 (module)

Angular 应用是模块化的,并且 Angular 有自己的模块系统,它被称为 Angular 模块或 NgModules。

每个Angular应用至少有一个模块(根模块),习惯上命名为AppModule。

根模块在一些小型应用中可能是唯一的模块,大多数应用会有很多特性模块,每个模块都是一个内聚的代码块专注于某个应用领域、工作流或紧密相关的功能。

Angular 模块(无论是根模块还是特性模块)都是一个带有@NgModule装饰器的类。

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

// src/app/app.module.ts

import { NgModule }   from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
 imports:   [ BrowserModule ],
 providers:  [ Logger ],
 declarations: [ AppComponent ],
 exports:   [ AppComponent ],
 bootstrap:  [ AppComponent ]
})
export class AppModule { }

其中重要的属性是:

  1. declarations - 声明本模块中拥有的视图类。Angular 有三种视图类:组件、指令、管道;
  2. exports - declarations 的子集,可用于其它模块的组件;
  3. imports - 本模块声明的组件模板需要的类所在的其它模块。用来导入其他自定义模块,第三方插件模块;
  4. providers - 服务的创建者,并加入到全局服务列表中,可用于应用任何部分;
  5. bootstrap - 指定应用的主视图(称为根组件),它是所有其它视图的宿主。只有根模块才能设置bootstrap属性。通常在main.ts中引导AppModule,这样platformBrowserDynamic().bootstrapModule(AppModule)

2. 组件 (component)

组件负责控制屏幕上的一小块区域,我们称之为视图。

下面是一个组件的简单例子:

// src/app/hero-list.component.ts

export class HeroListComponent implements OnInit {
 heroes: Hero[];
 selectedHero: Hero;

 constructor(private service: HeroService) { }

 ngOnInit() {
  this.heroes = this.service.getHeroes();
 }

 selectHero(hero: Hero) { this.selectedHero = hero; }
}

3. 模板 (template)

模板就是HTML文件,但是不是标准的HTML文件,它使用了一些模板语法,模板语法使模板有了自己的逻辑关系,并能够实现和组件的简单数据交互。

下面是一个简单的模板:

// src/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>

通常使用ng g component my-comoponent命令产生一个组件包含四个文件:

my-comoponent.css      // 样式文件
my-comoponent.thml      // 模板
my-comoponent.spec.ts    // 测试文件
my-comoponent.ts      // 这是组件? 通常我们认为这四个文件组成一个组件

4. 元数据 (metadata)

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

其实,在Angular中每个组件只是一个类,但是我们可以通过装饰器来附加元数据告诉Angular这是一个组件。

下面就是HeroListComponent的一些元数据。

// src/app/hero-list.component.ts (metadata)

@Component({  // @Component 将后面的 HeroListComponent 类标记为一个组件
 selector:  'hero-list',
 templateUrl: './hero-list.component.html',
 providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

@Component装饰器能接受一个配置对象, Angular 会基于这些信息创建和展示组件及其视图。

@Component的配置项包括:

  1. selector: CSS选择器,它告诉Angular在父级HTML中查找<hero-list>标签,创建并插入该组件。 例如,如果应用的HTML 包含<hero-list></hero-list>, Angular就会把HeroListComponent的一个实例插入到这个标签中;
  2. templateUrl:组件HTML 模板的模块相对地址;
  3. providers - 组件所需服务的依赖注入提供商数组。 这是在告诉 Angular:该组件的构造函数需要一个HeroService服务,这样组件就可以从服务中获得英雄数据。

到这里你应该可以明白:模板、元数据和组件共同描绘出这个视图。

5. 数据绑定 (databinding)

数据绑定是Angular中最常用的数据处理模式。数据绑定在模板与对应组件的交互中扮演了重要的角色,在父组件与子组件的通讯中也同样重要。

下面是一个简单的例子:

// src/app/hero-list.component.html 

<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>
  1. {{hero.name}}插值表达式在<li>标签中显示组件的hero.name属性的值;
  2. [hero]属性绑定把父组件HeroListComponent的selectedHero的值传到子组件HeroDetailComponent的hero属性中;
  3. (click) 事件绑定在用户点击英雄的名字时调用组件的selectHero方法。

Angular默认没有双向绑定,但是,官方推荐这样来实现双向绑定:

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

Angular 在每个 JavaScript 事件循环中处理所有的数据绑定,它会从组件树的根部开始,递归处理全部子组件。

6. 指令 (directive)

由于Angular模板是动态的,所以你需要通过指令实现对DOM的转换。(组件是一个带模板的指令;@Component装饰器实际上就是一个@Directive装饰器,只是扩展了一些面向模板的特性。 )

指令分为两种:结构指令、属性指令。

a. 结构指令: 通过在 DOM 中添加、移除和替换元素来修改布局。

下面是一个简单的内置结构指令的例子:

<!-- src/app/hero-list.component.html (structural) -->

<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>
  1. *ngFor告诉 Angular 为heroes列表中的每个英雄生成一个<li>标签。
  2. *ngIf表示只有在选择的英雄存在时,才会包含HeroDetail组件。

b. 属性指令:修改一个现有元素的外观或行为。

简单例子:

<!-- src/app/hero-detail.component.html -->
<input [(ngModel)]="hero.name">

7. 服务 (service)

服务是一个广义范畴,包括:值、函数,或应用所需的特性。几乎任何东西都可以是一个服务。 典型的服务是一个类,具有专注的、明确的用途。它应该做一件特定的事情,并把它做好。

例如:

  1. 日志服务
  2. 数据服务
  3. 消息总线
  4. 税款计算器
  5. 应用程序配置

组件类应保持精简。组件本身不从服务器获得数据、不进行验证输入,也不直接往控制台写日志。 它们把这些任务委托给服务。所以说服务是跑腿的,服务一般用来处理业务逻辑,被注入在组件当中,服务是全局单例的。也就是说注入到所有组件中的服务是同一个。

一个简单的例子:

// src/app/hero.service.ts 

export class HeroService {
 private heroes: Hero[] = [];

 constructor(
  private backend: BackendService,
  private logger: Logger) { }

 getHeroes() {
  this.backend.getAll(Hero).then( (heroes: Hero[]) => {
   this.logger.log(`Fetched ${heroes.length} heroes.`);
   this.heroes.push(...heroes); // fill cache
  });
  return this.heroes;
 }
}

8. 依赖注入 (denpendency injection)

“依赖注入”是提供类的新实例的一种方式,还负责处理好类所需的全部依赖。大多数依赖都是服务。 Angular 使用依赖注入来提供新组件以及组件所需的服务。

来看注入方式:

// src/app/hero-list.component.ts

constructor(private service: HeroService) { }

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

通常我们将服务声明在根模块,以便在整个应用中使用这个服务。

// src/app/app.module.ts

providers: [
 BackendService,
 HeroService,
 Logger
],

也可以在其他组件中声明服务,那么这个服务只能用于当前组件。把它注册在组件级表示该组件的每一个新实例都会有一个服务的新实例。

// src/app/hero-list.component.ts

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

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

Javascript 相关文章推荐
JQuyer $.post 与 $.ajax 访问WCF ajax service 时的问题需要注意的地方
Sep 20 Javascript
jQuery不兼容input的change事件问题解决过程
Dec 05 Javascript
基于canvas实现的绚丽圆圈效果完整实例
Jan 26 Javascript
AngularJs中route的使用方法和配置
Feb 04 Javascript
js实现图片切换(动画版)
Dec 25 Javascript
JavaScript实现瀑布流以及加载效果
Feb 11 Javascript
Agularjs妙用双向数据绑定实现手风琴效果
May 26 Javascript
详解ES6通过WeakMap解决内存泄漏问题
Mar 09 Javascript
vue axios post发送复杂对象问题
Jun 04 Javascript
利用d3.js制作连线动画图与编辑器的方法实例
Sep 05 Javascript
解决layui表格内文本超出隐藏的问题
Sep 12 Javascript
es6函数之箭头函数用法实例详解
Apr 25 Javascript
vue之数据交互实例代码
Jun 20 #Javascript
jquery加载单文件vue组件的方法
Jun 20 #jQuery
Angular.JS中select下拉框设置value的方法
Jun 20 #Javascript
原生js二级联动效果
Jun 20 #Javascript
angularjs下拉框空白的解决办法
Jun 20 #Javascript
JS使用ActiveXObject实现用户提交表单时屏蔽敏感词功能
Jun 20 #Javascript
20行js代码实现的贪吃蛇小游戏
Jun 20 #Javascript
You might like
自动完成JS类(纯JS, Ajax模式)
2009/03/12 Javascript
jQuery 1.5 源码解读 面向中高阶JSER
2011/04/05 Javascript
限制textbox或textarea输入字符长度的JS代码
2013/10/16 Javascript
jQuery学习之prop和attr的区别示例介绍
2013/11/15 Javascript
JQ实现新浪游戏首页幻灯片
2015/07/29 Javascript
AngularJS实现分页显示数据库信息
2016/07/01 Javascript
详解使用vue脚手架工具搭建vue-webpack项目
2017/05/10 Javascript
vue实现移动端图片裁剪上传功能
2020/08/18 Javascript
Vue 菜单栏点击切换单个class(高亮)的方法
2018/08/22 Javascript
react 兄弟组件如何调用对方的方法示例
2018/10/23 Javascript
Angular6 Filter实现页面搜索的示例代码
2018/12/02 Javascript
如何解决.vue文件url引用文件的问题
2019/01/18 Javascript
详解用场景去理解函数柯里化(入门篇)
2019/04/11 Javascript
解决LayUI数据表格复选框不居中显示的问题
2019/09/25 Javascript
js常用方法、检查是否有特殊字符串、倒序截取字符串操作完整示例
2020/01/26 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
[03:40]DOTA2亚洲邀请赛小组赛第二日 赛事回顾
2015/01/31 DOTA
Python编写百度贴吧的简单爬虫
2015/04/02 Python
详解在Python程序中使用Cookie的教程
2015/04/30 Python
Pycharm学习教程(2) 代码风格
2017/05/02 Python
Python 含参构造函数实例详解
2017/05/25 Python
带你了解python装饰器
2017/06/15 Python
使用tensorflow实现线性svm
2018/09/07 Python
Python利用递归实现文件的复制方法
2018/10/27 Python
pandas读取csv文件,分隔符参数sep的实例
2018/12/12 Python
对django xadmin自定义菜单的实例详解
2019/01/03 Python
详解python中init方法和随机数方法
2019/03/13 Python
pytorch 在sequential中使用view来reshape的例子
2019/08/20 Python
pytorch中获取模型input/output shape实例
2019/12/30 Python
意大利一家专营包包和配饰的网上商店:Borse Last Minute
2019/08/26 全球购物
自我鉴定范文
2013/11/10 职场文书
建筑安全员岗位职责
2014/03/13 职场文书
农村文化活动总结
2014/08/28 职场文书
大学迎新生标语
2014/10/06 职场文书
行政处罚事先告知书
2015/07/01 职场文书
新店开张宣传语
2015/07/13 职场文书