Angular 2-组件

来源:互联网 发布:淘宝99大促 编辑:程序博客网 时间:2024/05/20 22:26

1. 组件概述

组件之于ng,正如汽车部件之于汽车。一个模块包含多个组件,像是汽车的一个系统比如动力系统包含多个零件。一个模块的组件不能调用另外一个模块的组件。

Angular应用像是一棵树,组件是叶子,模块是枝干,根模块是树干。

2. 组件创建步骤

创建一个组件包括了三个步骤:
1.从@angular/core中引入Component装饰器;
2.建立一个普通类,并用@Component修饰它;
3.在@Component中,设置了selector自定义标签和template模板。

//contactItem.component.tsimport { Component } from '@angular/core';@Component({    selector: 'contact-item',    template: `        <div>            <p>张三</p>        </div>    `})export class ContactItemComponent{}

3. 组件元数据

主要包括了selector、template、styles。

selector:它是组件在HTML代码中标签,是组件的命名标记。它的命名采用“烤肉串式”,如“contact-app”;

templatetemplateUrltemplate提供了内联文档,templateUrl则指定外部文档URL地址,如templateUrl: 'app/components/contact-item.html'

stylesstyleUrlsstyles同理,styles指定内联样式,styleUrls指定外联样式表文件,如styleUrls: ['app/list/item.component.css']。styleUrl的等级高。

4. 组件与模板的交互

模板即组件的宿主元素,它与组件的交互形式有三种:

  • 显示数据
  • 双向数据绑定
  • 监听宿主元素事件以及调用组件方法

显示数据:{{}}显示组件数据,即把数据从内存中展示到页面上去。

import { Component } from '@angular/core';@Component({  selector: 'contact-item',  template: `    <div>      <p>{{name}}</p>    </div>   ` })export class ContactItemComponent{  name: string = '张三';}

双向数据绑定[(ngModel)] = "property"实现了该交互。

import { Component } from '@angular/core';@Component({  selector: 'contact-item',  template: `    <div>      <input type='text' value="{{name}}" [(ngModel)]="name"/>      <p>{{name}}</p>    </div>   ` })export class ContactItemComponent{  name: string = '张三';}

监听宿主元素事件以及调用组件方法:(eventName)方式调用,如<h3>添加联系人<i (click)="addContact()"></i></h3>

5. 组件之间的交互

包含了父子组件交互和非父子关系组件交互。交互的对象为组件的属性或者方法,从而实现数据双向流动。非父子关系组件的交互依靠服务来实现交互通信。

5.1 组件输入输出属性

Angular 2中@Input@Output分别实现了组建数据的输入输出。@Input为其他组件输入到本组件的数据,@Output为本组件输出到其他组件的数据。输入输出的数据除了可以是属性,也可能是一个动作,如点击事件。

//item.component.tsexport class ListItemComponent implements OnInit{  @Input() contact:any = {};  @Output() routerNavigate = new EventEmitter<number>();}//...<!-- list.component.html --><li *ngFor="let contact of contacts">  <list-item [contact]="contact (routerNavigate)="routerNavigate($event)"></list-item> </li>

note:[ ]是模板到组件内存,而( )是内存到模板。

5.2 父组件向子组件传递数据

子组件通过@Input接受或拦截来自父组件的数据。数据流动的路径为:父组件–>父组件模板–>嵌套的子组件selector–>子组件模板。

//父组件list.component.tsimport { Component, OnInit } from '@angular/core';@Component({  selector: 'list',  template: `    <ul class='list'>      <li *ngFor="let contact of contacts">        <list-item [contact]="contact"></list-item>      </li>    </ul>  `})export class ListComponent implements OnInit{  //...  this.contacts = data;}//子组件item.component.ts@Component({  selector: 'list-item',  template: `    <div class='contact-info'>      <label class='contact-name'>{{contact.name}}</label>      <span class='contact-tel'>{{contact.telNum}}</span>    </div>  `})export class ListItemComponent implements OnInit{  @Input() contact:any = {};}

拦截输入属性有两种方式:

  • setter拦截输入属性
  • ngOnchanges监听数据变化

setter拦截输入属性:getter和setter配套使用,提供了一套属性读写的封装。父组件到子组件数据流动中子组件可以改写为:

@Component({  selector: 'list-item',  template: `    <div class='contact-info'>      <label class='contact-name'>{{contactObj.name}}</label>      <span class='contact-tel'>{{contactObj.telNum}}</span>    </div>  `})export class ListItemComponent implements OnInit{  _contact: object = {};  @Input()  set contactObj(contace: object){    this._contact.name = (contact.name && contact.name.trim() || 'no name set');    this._contact.telNum = contact.telNum || '000-000';  }  get contactObj(){    return this._contact;  }}

其中,set对@Inputcontact进行处理后,通过get方式返回。contactObjListItemComponent的一个属性。

ngOnchanges监听数据变化:用于及时响应NG在属性绑定中发生的数据变化,该方法接收一个对象参数,包含了当前值和变化前的值。该对象参数为SimpleChanges,当前值和变化前的值分别为currentValuepreviousValue。一个例子,编辑联系人后,日志输出变化前后的值:

//父组件,detail.component.tsimport { Component } from '@angular/core';@Component({  selector: 'detail',  template: `    <a class='edit' (click)="editContact()">编辑</a>    <change-log [contact]="detail"></change-log>  `})export class DetailComponent implements OnInit{  detail:any = {};  //完成联系人编辑修改  editContact(){    //...    this.detail = data;  }}//子组件,changelog.component.tsimport { Component,Input,Onchanges,SimpleChanges } from '@angular/core';@Component({  selector: 'change-log',  template:    <h4>Change log:</h4>    <ul>      <li *ngFor="let change of changes">{{change}}</li>    </ul>  `})export class ChangeLogComponent implements Onchanges{  @Input() contact: any={};  changes: string[] = [];  ngOnChange(changes: {[propKey:string]: SimpleChanges}){    let log: string[] = [];    for(let propName in changes){      let changedProp = changes[propName],      from = JSON.stringify(changedProp.previousValue),      to = JSON.stringify(changedProp.currentValue);      log.push(`${propName} changed from ${from} to ${to}`);    }    this.changes.push(log.join(', ');  }}

5.3 子组件向父组件传递数据

使用事件传递是子组件向父组件传递数据最常用的方式。子组件需要实例化一个用来订阅和触发自定义事件的EventEmitter类,这个实例化对象是一个由装饰器@Output修饰的输出属性。下面是一个例子:

//父组件collection.component.tsimport { Component } from '@angular/core';@Component({  selector: 'collection',  template: `    <contact-collect [contact]="detail" (onCollect)="collectTheContact($event)"></contact-collect>  `})export class CollectionComponent implements OnInit{  detail: any = {};  collectTheContact(){    this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;  }}//子组件contactCollect.component.tsimport { Component } from '@angular/core';@Component({  selector: 'contact-collect',  template: `    <i [ngClass]="{collected: contact.collection}" (click)="collectTheContact()">收藏</i>  `})export class CollectionComponent implements OnInit{  @Input() contact: any = {};  @Output() onCollect = new EventEmitter<boolean>();  collectTheContact(){    this.onCollect.emit();  }}

子组件实例化一个boolean类型的EventEmitter,当click子组件模板时候,向父组件发送事件,接着父组件同名(与EventEmitter同名)的事件被触发。

5.4 其他组件交互方式

父子组件的数据传递方式还有两种:

  • 通过局部变量实现数据交互
  • 使用@ViewChild实现数据交互

通过局部变量实现数据交互:解决了父组件无法调用子组件相关成员变量和方法的问题。它的实现是在父组件模板中的子组件标签上绑定一个以#号标记的变量符号。该局部变量仅在父组件模板中使用,而不能再父组件类中直接使用。一个例子如下:

import { Component } from '@angular/core';@Component({  selector: 'collection',  template: `    <contact-collect (onCollect)="collectTheContact($event)" #contact></contact-collect>  `})export class CollectionComponent{ }

6. 组件生命周期

组件的生命周期,从组件创建、渲染,到数据变通时间的触发,再到组件从DOM移除,NG提供一系列钩子。这些钩子可以让开发者在这是些事件触发时,执行相应的回调函数。

每个生命周期钩子(接口)都对应着一个名为“ng+接口名”的方法。

NG的生命周期有以下8种,按照先后顺序依次调用钩子方法:

  • ngOnChanges
  • ngOnInit
  • ngDoCheck
  • ngAfterContentInit
  • ngAfterContentChecked
  • ngAfterViewInit
  • ngAfterViewChecked
  • ngOnDestroy

ngOnChanges:响应组件输入值发生变化时触发的事件,这里的输入值指的是通过@Input装饰器显式指定的变量。该方法接收一个SimpleChanges对象,包含当前值和变化前的值。

ngOnInit:用于数据绑定输入属性之后初始化组件。通常用来获取数据,并且很容易进行Hook操作。

ngDoCheck:用于变化检测,该钩子方法会在每次变化监测发生时被调用。在一个变化检测周期内,无论是否发生变化,ngDoCheck都会被调用。ngOnChangesngDoCheck不同时使用,ngDoCheck监测的粒度更小。

//……

原创粉丝点击