详解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 相关文章推荐
jquery插件开发之实现jquery手风琴功能分享
Mar 10 Javascript
Node.js和PHP根据ip获取地理位置的方法
Mar 14 Javascript
JavaScript+html5 canvas实现本地截图教程
Apr 16 Javascript
javascript点击按钮实现隐藏显示切换效果
Feb 03 Javascript
Vue.js递归组件构建树形菜单
Dec 24 Javascript
vue结合Echarts实现点击高亮效果的示例
Mar 17 Javascript
jQuery中ajax请求后台返回json数据并渲染HTML的方法
Aug 08 jQuery
LayUI表格批量删除方法
Aug 15 Javascript
js防抖和节流的深入讲解
Dec 06 Javascript
VUE实现移动端列表筛选功能
Aug 23 Javascript
layui上传图片到服务器的非项目目录下的方法
Sep 26 Javascript
vue配置型表格基于el-table拓展之table-plus组件
Apr 12 Vue.js
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
php xml 入门学习资料
2011/01/01 PHP
真正根据utf8编码的规律来进行截取字符串的函数(utf8版sub_str )
2012/10/24 PHP
在win系统安装配置 Memcached for PHP 5.3 图文教程
2015/03/03 PHP
PHP中的静态变量及static静态变量使用详解
2015/11/05 PHP
PHP实现搜索时记住状态的方法示例
2018/05/11 PHP
Laravel框架路由和控制器的绑定操作方法
2018/06/12 PHP
基于jQuery图片平滑连续滚动插件
2009/04/27 Javascript
基于JQuery的日期联动实现代码
2011/02/24 Javascript
js 用CreateElement动态创建标签示例
2013/11/20 Javascript
js实现头像图片切割缩放及无刷新上传图片的方法
2015/07/17 Javascript
Angularjs 滚动加载更多数据
2016/03/17 Javascript
jQuery命名空间与闭包用法示例
2017/01/12 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
Nodejs进阶之服务端字符编解码和乱码处理
2017/09/04 NodeJs
Layui数据表格之获取表格中所有的数据方法
2018/08/20 Javascript
jquery 动态遍历select 赋值的实例
2018/09/12 jQuery
webpack+vue-cil 中proxyTable配置接口地址代理操作
2020/07/18 Javascript
jquery实现点击左右按钮切换图片
2021/01/27 jQuery
python 采集中文乱码问题的完美解决方法
2016/09/27 Python
Python中的错误和异常处理简单操作示例【try-except用法】
2017/07/25 Python
Python使用requests及BeautifulSoup构建爬虫实例代码
2018/01/24 Python
Python爬虫小技巧之伪造随机的User-Agent
2018/09/13 Python
关于pytorch处理类别不平衡的问题
2019/12/31 Python
详解android与HTML混合开发总结
2018/06/06 HTML / CSS
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
Java语言程序设计测试题判断题部分
2013/01/06 面试题
平面设计的岗位职责
2013/11/08 职场文书
高中生期末评语大全
2014/01/28 职场文书
绩效管理实施方案
2014/03/19 职场文书
加强机关作风建设心得体会
2014/10/22 职场文书
吃空饷专项整治方案
2014/10/27 职场文书
毕业论文指导教师评语
2014/12/30 职场文书
2015年党风廉政建设责任书
2015/01/29 职场文书
SpringBoot项目中控制台日志的保存配置操作
2021/06/18 Java/Android
解决Laravel使用验证时跳转到首页的问题
2021/11/17 PHP
css清除浮动clearfix:after的用法详解(附完整代码)
2023/05/21 HTML / CSS