Angular 2-组件

1. 组件概述

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

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

2. 组件创建步骤

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

//contactItem.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'contact-item',
    template: `
        
<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: `
    
<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)方式调用,如

添加联系人

5. 组件之间的交互

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

5.1 组件输入输出属性

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

//item.component.ts
export class ListItemComponent implements OnInit{
  @Input() contact:any = {};
  @Output() routerNavigate = new EventEmitter();
}
//...


  • "let contact of contacts"> <list-item [contact]="contact (routerNavigate)="routerNavigate($event)">
  • note:[ ]是模板到组件内存,而( )是内存到模板。

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

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

    //父组件list.component.ts
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'list',
      template: `
        
      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}} class='contact-tel'>{{contact.telNum}} 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}}
          class='contact-tel'>{{contactObj.telNum}}
        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.ts
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'detail',
      template: `
        class='edit' (click)="editContact()">编辑a>
        <change-log [contact]="detail">change-log>
      `
    })
    
    export class DetailComponent implements OnInit{
      detail:any = {};
      //完成联系人编辑修改
      editContact(){
        //...
        this.detail = data;
      }
    }
    
    
    //子组件,changelog.component.ts
    import { Component,Input,Onchanges,SimpleChanges } from '@angular/core';
    
    @Component({
      selector: 'change-log',
      template:
        

    Change log:

    • "let change of changes">{{change}}
    ` }) 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.ts
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'collection',
      template: `
        "detail" (onCollect)="collectTheContact($event)">
      `
    })
    
    export class CollectionComponent implements OnInit{
      detail: any = {};
      collectTheContact(){
        this.detail.collection == 0 ? this.detail.collection = 1 : this.detail.collection = 0;
      }
    }
    
    
    //子组件contactCollect.component.ts
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'contact-collect',
      template: `
        "{collected: contact.collection}" (click)="collectTheContact()">收藏
      `
    })
    
    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: `
        "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监测的粒度更小。

    //……

    你可能感兴趣的:(angular)