Angular学习(二)【组件】

本文深入探讨Angular中的组件,包括组件的创建、组件元数据、模板和组件类。讲解了如何使用@Component装饰器创建组件,以及组件的生命周期钩子,如ngOnInit、ngOnChanges等。此外,还阐述了组件的数据绑定机制,如显示数据、双向数据绑定和监听事件。了解这些基础知识对于掌握Angular应用的构建至关重要。

组件

前端中的组件是一堆为了实现同一业务逻辑的代码文件的组合,将相关文件都放到同一个目录中,就形成了一个独立性非常强的组件。

Angular 中使用了Web Component 的标准来实现组件化。

组件是 Angular 应用的最小的逻辑单元,模块则是在组件之上的一层抽象。组件以及其他部分,如指令、管道、服务、路由等都可以被包含到一个模块中,外部通过引用这个模块来使用一系列封装好的功能。

可以把 Angular 应用想象成一棵树,模块是这棵树的树枝,组件是这棵树的叶子,每个 Angular 应用都必须要有一个根模块(树干),并且根模块中必须通过 Bootstrap 指定根组件,用于启动 Angular 应用。

创建组件

创建组件跟简单,可以通过一下三个步骤创建组件:

  1. @angular/core 中引入 Component 装饰器;
  2. 建立一个普通的类,并用 @Component 修饰它;
  3. @Component 中,设置 selector 自定义标签和 template/templateUrl 模板以及 styles/styleUrls 样式。
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent { }

在新版的 Angular 中自定义标签需要以 app- 开头,否则会报错。

以上代码会创建一个最简单的 Angular 组件,使用这个组件需要在 HTML 中添加 <app-root></app-root> 标签,然后 Angular 便会在此标签中插入组件中指定的模板。

组件的基础构成

组件由组件装饰器、组件元数据、模板和组件类组成。先来了解一下组件装饰器和组件类,后面有章节详细说明组件元数据和模板。

组件装饰器( Component Decorator )

每个组件类必须使用 @Component 进行修饰才能成为 Angular 组件; @Component 是 TypeScript 的语法,它是一个装饰器,任何一个 Angular 的组件都会用这个装饰器修饰,如果移除了这个装饰器,它将不再是 Angular 组件了。

组件类

组件实际上也是一个普通的类,组件的逻辑都在组件类里定义并实现。


组件元数据

在组件中的 @Component 装饰器部分,提供了额外的元数据以确定如何在运行时处理、实例化和使用组件:

  • selector:用于定义组件标签名,也是此组件的元素选择器;
  • template:定义组件宿主元素的模板;
  • templateUrl:引用外联模板;
  • styles:要应用于此组件视图的内联定义样式;
  • styleUrls:要应用于此组件视图的外联样式表;
  • animations:此组件的动画列表;
  • providers:此组件及其子组件可用的 providers 列表;
  • viewProviders:此组件及其视图子项可用的 providers 列表;
  • exportAs:在模板中导出组件实例的名称;
  • inputs:以数据绑定为组件输入类属性名称列表;
  • moduleId:定义此组件的 ES/CommonJS 模块 ID;
  • outputs:显示其他人可以订阅的输出事件的类属性名称列表;
  • host:将类属性映射到元素绑定的事件和属性;
  • encapsulation:此组件使用的样式封装策略;
  • interpolation:在此组件模板中使用的自定义插值标记;
  • queries:配置可以注入组件的查询;
  • changeDetection: 更改此组件使用的检测策略.

每个组件只能指定一个模板,可以使用 template 或者 templateUrl 的引入方式。

stylesstyleUrls 允许同时指定。如果同时指定,styles 中的样式会先被解析,然后才会解析 styleUrls 中的样式。


数据绑定

每个组件都会关联一个模板,这个模板最终会渲染到页面上,页面的这个 DOM 元素就是此组件实例的宿主元素;

组件是自描述的。可以与宿主元素交互,交互的形式包括:

  • 显示数据

可以再模板中使用插值语法 {{}} 来显示组件中的数据。

  • 双向数据绑定

在模板中通过形如 [(ngModel)]='property' 的方式进行双向数据绑定。

  • 监听宿主元素事件以及调用组件方法

在模板中通过形如 (click)='fun()' 的方法响应 UI 事件并调用组件中的方法。


组件的生命周期

组件的生命周期由 Angular 内部管理,从组件的创建、渲染,到数据变动事件的触发,再到组件从 DOM 中移除, Angular 都提供了一系列的钩子。这些钩子可以让开发者很方便的在这些事件触发时,执行相应的回调函数。

组件提供了八个生命周期钩子,下面分别来看一下:

ngOnChanges

ngOnint 钩子用于响应组件输入值发生变化时触发的事件。该方法接受一个 SimpleChanges 对象,包含当前值和变化前的值。该方法在ngOnint 之前,或者当数据绑定输入属性的值发生变化时会触发。

ngOnChanges 当且仅当组件输入数据变化时被调用,这里的“输入数据”指的是通过 @Input 装饰器显式指定的那些变量。只要这个输入属性的值发生了改变.就会触发 ngOnChanges() 生命周期钩子.这个生命周期钩子被调用时会传入一个 SimpleChanges 对象,这个对象中包含了输入属性当前值和上一值。

@Input() name: string;
ngOnChanges(changes: SimpleChanges): void {
  console.log(changes); // name:SimpleChange {previousValue: "a", currentValue: "ab", firstChange: false}
}

上面是定义了一个输入属性name并将从a它改为ab之后的打印结果,可能你还注意到了打印的结果中还有一个firstChange属性.它是一个Booleans,表明你是否是第一次改变。

同时,还有一点需要注意: 输入属性定义为引用类型和基本类型的时候其表现结果是不同的.当输入属性是基本类型时,每一次改变都会触发 ngOnChanges() 生命周期钩子,而当输入属性是引用类型时,改变引用类型 当中 的属性时,并不会触发 ngOnChanges() 生命周期钩子,只有将引用类型数据的指针指向另一块内存地址的时候才会触发 ngOnChanges() 生命周期钩子。

ngOnInit

ngOnint 钩子用于数据绑定输入属性之后初始化组件。该钩子方法会在第一次 ngOnChanges 之后被调用。

使用 ngOnInit 有以下两个重要的原因:

  1. 组件构造后不久就要进行复杂的初始化;
  2. 需要在输入属性设置完成之后才构建组件。

ngDoCheck

ngDoCheck 钩子用于变化监测,该方法会在每次变化监测发生时被调用,在 ngOnChanges()ngOnInit() 之后。

ngDoCheck() 是 Angular 中的变更检测机制.它由 zone.js 来实现的。其行为是只要你的 Angular 中的某个组件发生异步事件,就会检查整个组件树,以保证组件属性的变化或页面的变化是同步的,所以 ngDoCheck() 的触发相当频繁的.并且是我们无法预料到的,也许我们在页面上的一个无意识操作,就会触发几个甚至几十个的 ngDoCheck() 生命周期钩子。每一个变化监测周期内,不管数据值是否发生了变化,ngDoCheck 都会被调用,因此这个方法要慎用。所以我们在使用ngDoCheck()生命周期钩子的时候一定要加上判断.以避免无用的触发干扰我们.

ngAfterContentInit

ngAfterContentInit 钩子在组件内引用外部组件时,外部内容嵌入到组件视图后调用,它在第一次 ngDoCheck 执行后调用,且只执行一次。

当父组件向子组件投影内容的时,在子组件内会初始化父组件的投影内容,此时会调用 ngAfterContentInit() 生命周期钩子.在整个组件生命周期中只会调用一次.如下所示:

<!--- 父组件 --> 
<app-child>
  <p>我是父组件向子组件的投影内容</>
</app-child>
<!--- 子组件 ChildComponent --> 
<div>
  //接受父组件的投影内容
  <ng-content></ng-content>
</div>

ngAfterContentChecked

ngAfterContentChecked 钩子在组件内引用外部组件时,外部内容嵌入到组件视图后,或者每次变化监测的时候调用。ngAfterContentInit() 和每次 ngDoCheck() 之后调用。

当父组件向子组件的投影内容发生改变时会调用 ngAfterContentChecked() 生命周期钩子。它与 ngDoCheck() 类似,当投影内容发生改变时,就会执行变更检查机制,同时调用 ngAfterContentChecked() 生命周期钩子。此外,还有一点:当父组件和子组件都有投影内容时,会先执行父组件的生命周期钩子,它与下面要说的 ngAfterViewInit()ngAfterViewChecked() 相反.

ngAfterViewInit

ngAfterViewInit 钩子会在 Angular 创建了组建的视图及其子视图之后被调用。在第一次 ngAfterContentChecked() 之后调用,只调用一次。

ngAfterViewChecked

ngAfterViewChecked 在 Angular 创建了组件的视图及其子组件视图之后被调用一次,并且在每次子组件变化监测时也会被调用。

当组件及其子组件的视图发生改变时,执行完变更检查机制后调用.当父组件和子组件都发生视图变化时,会先执行子组件的生命周期钩子.

注意: 这里所说的视图发生改变不一定是真正页面上的变化.只是Angular种所认为的视图变化.因为Angular本身并不能察觉到页面上显示的视图.所以在Angular认为,只要你在后台定义的属性发生了改变,就是视图有了变化.从而就会调用ngAfterViewChecked()生命周期钩子.

ngOnDestroy

ngOnDestroy 在销毁组件之前触发。那些不会垃圾自动回收的资源(比如已订阅的观察者事件、绑定过的 DOM 事件。通过 setTimeOut 或 setInterval 设置过得计时器等等)都应该在 ngOnDestroy 中手动销毁掉,从而避免发生内存泄漏等问题。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值