ng2組件

組件基礎

組件用來包裝特定的功能,應用程序的有序運行依賴于組件之間的協(xié)同工作。
組件是angular應用的最小邏輯單元,模塊則是在組件之上的一層抽象。所有angular組件都可以獨立存在,也意味著任何組件都可以作為根組件被引導,也可以被路由加載,或在其他組件中使用。不過一個組件不能單獨被啟動,它必須被包裝到模塊里,然后通過Bootstrap模塊接口引導入口模塊來啟動angular應用。

創(chuàng)建組件的步驟

創(chuàng)建angular組件三步驟:

  1. @angular/core中引入Component裝飾器
  2. 建立一個普通的類,并用@Component修飾它
  3. @Component中,設置selector自定義標簽和template模板
//contactItem.component.ts
import { Component } from '@angular/core';
@Component({
    selector:'contact-item',
    template:`
        <div>
            <p>張三</p>
            <p>13800000</p>
        </div>
    `
})
export class ContactItemComponent {}

以上代碼創(chuàng)建了一個最簡單的組件。使用這個組件需要在HTML中添加<contact-item>自定義標簽,然后angular便會在此標簽中插入ContactItemComponent組件中指定的模板。

<div>
    <contact-item></contact-item>
</div>

最終會被渲染成:

<div>
    <contact-item>
        <div>
            <p>張三</p>
            <p>13800000</p>
        </div>
    </contact-item>
</div>

組件基礎構成

組件裝飾器

@Component是TypeScript的語法,它是一個裝飾器,任何一個angular的組件類都會用這個裝飾器修飾,如果移除了這個裝飾器,它將不再是angular的組件。

組件元數(shù)據(jù)

ContactItemComponent這個組件中的@Component裝飾器部分,使用到了大部分組件需要的元數(shù)據(jù):用于定義組件標簽名的selector;用于定義組件宿主元素模板的template

1.selector

selector是用于定義組件在HTML代碼中匹配的標簽,它將成為組件的命名標記。通常情況下都需要設置selector,特殊情況下也可以忽略,不指定時默認為匹配div元素,但不建議這樣做。selector的命名方式建議用“烤肉串式”命名,即采用小寫字母并以“-”分隔。

2.template

template是為組件指定一個內聯(lián)模板。使用ES6的多行字符串``語法能夠創(chuàng)建多行模板。

3.templateUrl

templateUrl是為組件指定一個外部模板的URL地址。

@Component({
    templateUrl:'app/component/contact-item.html'
})

每個組件只能指定一個模板,可以使用templatetemplateUrl的引入方式。

4.styles

styles是為組件指定內聯(lián)樣式。

@Component({
    styles:[
        `
        li:last-child{
            border-bottom:none;
        }
        `
    ]
})
5.styleUrls

styleUrls是為組件指定一系列用于該組件的外聯(lián)樣式表文件。

@Component({
    styleUrls:['app/list/item.component.css']
})

stylesstyleUrls允許同時指定。如果同時指定,styles中的樣式會先被解析,然后才會解析styleUrls中的樣式,換句話說,styles的樣式會被styleUrls的樣式覆蓋。另外,也可以在模板的DOM節(jié)點上直接寫樣式,它的優(yōu)先級最高。

模板

每個組件都必須設置一個模板,angular才能將組件內容渲染到DOM上,這個DOM元素叫做宿主元素。組件可以與宿主元素交互,交互的形式包括:

  • 顯示數(shù)據(jù):在模板中可以使用{{}}來顯示組件的數(shù)據(jù)。
//contactItem.component.ts
import { Component } from '@angular/core';
@Component({
    selector:'contact-item',
    template:`
        <div>
            <p>{{name}}</p>
            <p>{{phone}}</p>
        </div>
    `
})
export class ContactItemComponent{
    name:string='張三';
    phone:string='13800000';
}
  • 雙向數(shù)據(jù)綁定:[(ngModel)]="property"
  • 監(jiān)聽宿主元素事件以及調用組件方法:(click)="addContact()"

組件與模塊

組件通過與其他組件協(xié)作,完成一個完整的功能特性。這樣的功能特性通常會封裝到一個模塊里。
模塊是在組建之上的一層抽象,組件以及指令、管道、服務、路由等都能通過模塊去組織。

模塊的構成

angular提供了@NgModule裝飾器來創(chuàng)建模塊,一個應用可以有多個模塊,但有且只有一個根模塊,其他模塊叫做特性模塊。根模塊是啟動應用的入口模塊,根模塊必須通過bootstrap元數(shù)據(jù)來指定應用的根組件,然后通過bootstrapModule()方法來啟動應用。

//app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-brower';
import { ContactItemComponent } from './contactItem.component';
@NgModule({
    imports:[BrowserModule],
    declarations:[ContactItemComponent],
    bootstrap:[ContactItemComponent]
})
export class AppModule {}

//app.ts
import { platformBrowseerDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

bootstrap這個元數(shù)據(jù)用于指定應用的根組件,NgModule主要的元數(shù)據(jù)如下。

  • declarations:用于指定屬于這個模塊的視圖類,即指定哪些部件組成了這個模塊。angular有組件、指令和管道三種視圖類,這些視圖類只能屬于一個模塊,不能再次聲明屬于其他模塊的類。
  • exports:導出視圖類。當該模塊被引入到外部模塊時,這個屬性指定了外部模塊可以使用該模塊的哪些視圖類,所以它的值類型跟declarations一致(組件、指令和管道)。
  • imports:引入該模塊依賴的其他模塊或路由,引入后模塊里的組件模板才能引用外部對應的組件、指令和管道。
  • providers:指定模塊依賴的服務,引入后該模塊中的所有組件都可以使用這些服務。
視圖類引入

NgModule提供了declarations這個元數(shù)據(jù)來將指令、組件或管道等視圖類引入到當前模塊。
在上面的AppModule中,通過declarationsContactItemComponent組件引入到了AppModule模塊中,使得所有屬于AppModule模塊的其它組件的模板都可以使用<contact-item>。

//app.module.ts
@NgModule({
    declarations:[
        AppComponent,
        ListComponent,
        ListItemComponent,
        DetailComponent,
        CollectionComponent,
        EditComponent,
        HeaderComponent,
        FooterComponent,
        PhonePipe,
        BtnClickDirective
    ]
    //...
})
export class AppModule {}

如果在ListComponent組件的模板代碼list.component.html中,使用到了HeaderComponent、FooterComponentListItemComponent這三個組件,這個時候必須在ListComponent所屬的模塊(即AppModule)中,通過declarations引入這三個組件和ListItemComponent組件后才能在模板中使用他們。

<!--list.component.html-->
<!--組件中制定了HeaderComponent,才能使用my-header標簽-->
<my-header title="所有聯(lián)系" [isShowCreateButton]="true"></my-header>
<ul class="list">
    <li *ngFor="let contact of contacts">
        <list-item [contact]="contact" (routerNavigate)="routerNavigate($event)"></list-item>
    </li>
</ul>
<my-footer></my-footer>

ngFor是angular的內置指令,在引入BrowserModule的時候就已經(jīng)引入了常用的內置指令。

導出視圖類以及導入依賴模塊

有時候模塊中的組件、指令或管道,可能也會在其他模塊中使用??梢允褂?code>export元數(shù)據(jù)對外暴露這些組件、指令或管道。

//contact.module.ts
import { NgModule } from '@angular/core';
import { ContactItemComponent } from './contactItem.component';
@NgModule({
    declarations:[ContactItemComponent],
    exports:[ContactItemComponent] //導出組件
})
export class ContactModule {}

//message.module.ts
import { NgModule } from '@angular/core';
import { ContactModule } from './contact.module';
import { SomeOtherComponent } from './someother.component';
@NgModule({
    //在SomeOtherComponent組件的模板中可以使用到<contact-item>組件了
    declarations:[SomeOtherComponent],
    imports:[ContactModule] //導入模塊
})
export class MessageModule {}
服務引入

服務通常用于處理業(yè)務邏輯及相關的數(shù)據(jù)。引入服務有兩種方式:一種是通過@NgModuleproviders,另一種是通過@Componentproviders。

//app.module.ts
import { ContactService } from './shared';
//...
@NgModule({
    //...
    providers:[ContactService],
    bootstrap:[AppComponent]
})
export class AppModule {}

所有被包含在AppModule中的組件,都可以使用到這些服務。同樣,在組件中也可以用providers來引入服務,該組件及其子組件都可以公用這些引入的服務。

組件交互

組件交互就是組件通過一定的方式來訪問其他組件的屬性或方法,從而實現(xiàn)數(shù)據(jù)雙向流動。組件交互包括父子組件交互和一些非父子關系組件的交互。組件交互有很多方式,非父子關系的組件可以通過服務來實現(xiàn)數(shù)據(jù)交互通信。

組件的輸入輸出屬性

angular提供了輸入(@Input)和輸出(@Output)語法來處理組件數(shù)據(jù)的流入流出。

//item.component.ts
export 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>

ListItemComponent組件的作用是顯示單個聯(lián)系人的信息。由于聯(lián)系人列表數(shù)據(jù)是在ListCommponent組建中維護的,在顯示單個聯(lián)系人時,需要給ListItemComponent傳入單個聯(lián)系人數(shù)據(jù)。另外在單擊單個聯(lián)系人時,需要跳轉到此聯(lián)系人的明細信息,需要子組件通知父組件進行跳轉,[contact](routerNavigate)的輸入輸出變量,用于滿足上述功能。
這里的輸入輸出是以當前組件角度去說的,contactrouterNavigate分別是ListItemComponent組件的輸入和輸出屬性。輸出屬性一般是以事件的形式,將數(shù)據(jù)通過EventEmitter拋出去。
除了使用@Input@Output修飾外,還可以在組件的元數(shù)據(jù)中使用inputs、output來設置輸入輸出屬性,設置的值必須為字符串數(shù)組,元素的名稱需要和成員變量相對應。

@Component({
    inputs:['contact'],
    outputs:['routerNavigate']
})
export class ListItemComponent implements OnInit {
    contact:any={};
    routerNavigate=new EventEmitter<number>();
}

父組件向子組件傳遞數(shù)據(jù)

父組件的數(shù)據(jù)通過子組件的輸入屬性流入子組件,在子組件完成接收或攔截,以此實現(xiàn)了數(shù)據(jù)由上而下的傳遞。

父到子組件間的數(shù)據(jù)傳遞

父組件LIstComponent將獲取到聯(lián)系人的數(shù)據(jù),通過屬性綁定的方式流向子組件ListItemComponent

//list.component.ts
import { 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;//data為獲取到的聯(lián)系人數(shù)據(jù)
}
//item.component.ts
import { Component,OnInit,Input } from '@angular/core';
@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={};
}

在之前的例子中,app.module.ts中已經(jīng)通過@NgModule的元數(shù)據(jù)declarations將子組件ListItemComponent的實例引入到AppModule中,使得所有屬于AppModule中的其他組件都可以使用ListItemComponent組件,因此在父組件ListComponent中可直接引用該子組件。將每個聯(lián)系人對象通過屬性綁定的方式綁定到屬性contact中來供子組件來引用,數(shù)據(jù)由上而下流入子組件,在子組件中通過@Input裝飾器進行數(shù)據(jù)的接收。

攔截輸入屬性

子組件可以攔截輸入屬性的數(shù)據(jù)并進行相應的處理。有兩種攔截處理方式。

1.setter攔截輸入屬性

gettersetter通常配套使用,用來對屬性進行相關約束。他們提供了一些屬性讀寫的封裝。setter可以對屬性進行再封裝處理,對復雜的內部邏輯通過訪問權限控制來隔絕外部調用,以避免外部的錯誤調用影響到內部的狀態(tài)。同時也把內部復雜的邏輯結構封裝成高度抽象可被簡單調用的屬性,再通過getter返回要設置的屬性值。
通過輸入輸出屬性可以實現(xiàn)父子組件的數(shù)據(jù)交互,還可以通過setter來攔截來自父組件的數(shù)據(jù)源,并進行處理,使數(shù)據(jù)的輸出更合理。

//ListComponent.ts使用前面的例子
//ListItem.component.ts
@Component({
    selector:'list-item',
    template:`
        <div>
            <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(contact:object){
        this._contact.name=(contact.name&&contact.name.trim())||'no name seet';
        this._contact.telNum=contact.telNum||'000-000';
    }
    get contactObj(){ return this._contact; }
}

這里通過setter的方式設置一個contactObj屬性對象,其作用是對通過@Input修飾符獲取的數(shù)據(jù)contact進行二次處理,再通過getter返回這個contactObj對象。這樣處理的作用是使得聯(lián)系人不會出現(xiàn)nullundefined的情況。gettersetter其實是在組件類的原型對象上設置了一個contactObj屬性。

Object.defineProperty(ListItemComponent.prototype,"contactObj",{
    //...
})
2.ngOnChanges監(jiān)聽數(shù)據(jù)變化

ngOnChanges用于及時響應angular在屬性綁定中發(fā)生的數(shù)據(jù)變化,該方法接收一個對象參數(shù),包含當前值和變化前的值。在ngOnInit之前,或者當數(shù)據(jù)綁定的輸入屬性的值發(fā)生變化時會觸發(fā)。ngOnChanges是組件的生命周期鉤子之一。

//父組件detail.component.ts
import { 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={};
    //完成聯(lián)系人編輯修改
    editContact(){
        //...
        this.detail=data;//修改后的數(shù)據(jù)
    }
}
//子組件changelog.component.ts
import { 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[]=[];
    ngOnChanges(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(', '));
    }
}

SimpleChanges類是angular的一個基礎類,用于處理數(shù)據(jù)的前后變化,其包含兩個重要成員變量,分別是previousValuecurrentValue,previousValue是獲取變化前的數(shù)據(jù),currentValue是獲取變化后的數(shù)據(jù)。
ngOnChanges當且僅當組件輸入數(shù)據(jù)變化時被調用,“輸入數(shù)據(jù)”指的是通過@Input裝飾器顯式指定的那些數(shù)據(jù)。

子組件向父組件傳遞數(shù)據(jù)

使用事件傳遞是子組件向父組件傳遞數(shù)據(jù)的最常用方式。子組件需要實例化一個用來訂閱和觸發(fā)自定義事件的EventEmitter類,這個實例對象是一個由裝飾器@Output修飾的輸出屬性,當有用戶操作行為發(fā)生時該事件會被觸發(fā),父組件則通過事件綁定的方式來訂閱來自子組件觸發(fā)的事件。

//collection.component.ts  父組件
import { 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;
    }
}

父組件CollectionComponent通過綁定自定義事件onCollect訂閱來自子組件觸發(fā)的事件。當有來自子組件對應的事件被觸發(fā),在父組件中能夠監(jiān)聽到該事件。

//contactCollect.component.ts  子組件
import { Component,EventEmitter,Input,Output } from '@angular/core';
@Component({
    selector:'contact-collect',
    template:`
        <i [ngClass]="{collected:contact.collection}" (click)="collectTheContact()"收藏</i>
    `
})
export class ContactCollectComponent {
    @Input() contact:any={};
    @Output() onCollect=new EventEmitter<boolean>();
    collectTheContact(){
        this.onCollect.emit();
    }
}

其他組件交互方式

父子組件間數(shù)據(jù)傳遞的實現(xiàn)還有兩種方式:

  • 父組件通過局部變量獲取子組件引用
  • 父組件使用@ViewChild獲取子組件的引用
通過局部變量實現(xiàn)數(shù)據(jù)交互

模板局部變量可以獲取子組件的實例引用。通過創(chuàng)建模板局部變量的方式,來實現(xiàn)父組件與子組件數(shù)據(jù)交互,即在父組件的模板中為子組件創(chuàng)建一個局部變量,這個父組件可以通過這個局部變量來獲得讀取子組件公共成員變量和函數(shù)的權限。模板局部變量的作用域范圍僅存在于定義該模板局部變量的子組件。

//父組件collection.component.ts
import { Component } from '@angular/core';
@Component({
    selector:'collection',
    template:`
        <contact-collect (click)="collectTheContact()" #collect></contact-collect>
    `
})
export class CollectionComponent {}
//子組件contactcollect.component.ts
import { Component } from '@angular/core';
@Component({
    selector:'contact-collect',
    template:`
        <i [ngClass]="{collect:detail.collection}">收藏</i>
    `
})
export class ContactCollectComponent{
    detail:any={};
    collectTheContact() {
        this.deetail.collection==0?this.detail.collection=1:this.detail.collection=0;
    }
}

這里通過在標簽元素<contact-collect>中放置一個局部變量collect,用來獲取子組件的實例引用,來訪問子組件中的成員變量和方法。

使用@ViewChild實現(xiàn)數(shù)據(jù)交互

當父組件需要獲取到子組件中變量或方法的讀寫權限時,可以通過@ViewChild注入的方式來實現(xiàn)。組件中元數(shù)據(jù)ViewChild的作用是聲明對子組件元素的實例引用,它提供了一個參數(shù)來選擇將要引用的組件元素,這個參數(shù)可以是一個類的實例,也可以是一個字符串。

  • 參數(shù)為類實例,表示父組件將綁定一個指令或子組件實例
  • 參數(shù)為字符串類型,表示將起到選擇器的作用,即相當于在父組件中綁定一個模板局部變量,獲取到子組件的一份實例對象的引用

組件中元數(shù)據(jù)ViewChild的參數(shù)為字符串的實現(xiàn)方式和綁定模板局部變量是一樣的。

import { Component,AfterViewInit,ViewChild } from '@angular/core';
@Component({
    selector:'collection',
    template:`
        <contact-collect (click)="collectTheContact()"></contact-collect>
    `
})
export class CollectionComponent{
    @ViewChild(ContactCollectComponent) contactCollect:CotactCollectComponent;
    ngAfterViewInit(){
        //...
    }
    collectTheContact(){
        this.contactCollect.collectTheContact();
    }
}

組件內容嵌入

內容嵌入通常用來創(chuàng)建可復用組件。

import { Component } from '@angular/core';
@Component({
    selector:'example-content',
    template:`
        <div>
            <h4>ng-content 示例</h4>
            <div style="background-color:gray;padding:5px;margin:2px">
                <ng-content select="header"></ng-content>
            </div>
        </div>
    `
})
class NgContentExampleComponent {}

接著再定義一個根組件來使用它。

import { Component } from 'angular/core';
@Component({
    selector:'app',
    template:`
        <example-content>
            <header>Header content</header>
            <!--將自定義的內容放到 example-content標簽之間-->
        </example-content>
    `
})
export class NgContentAppComponent {}

最后組件的DOM樹會被渲染成:

<app>
    <example-content>
        <div>
            <h4>ng-content示例</h4>
            <div style="background-color:gray;padding:5px;margin:2px">
                <ng-content select="header"></ng-content>
            </div>
        </div>
    <example-content>
</app>

<example-content>標簽之間的內容,也就是<header>Header content</header>,被填充到ng-content,而NgContentExampleComponent組件模板中的其他元素沒有受到影響。select="header"表示匹配<example-content>標簽之間的第一個header標簽,并將其填充到相應的ng-content中。
還可以同時使用多個嵌入內容。

import { Component } from '@angular/core';
@Component({
    selector:'example-content',
    template:`
        <div>
            <h4>component with ng-content</h4>
            <div style="background-color:green;padding:5px;margin:2px">
                <ng-content select="header"></ng-content>
            </div>
<div style="background-color:gray;padding:5px;margin:2px">
                <ng-content select=".class-select"></ng-content>
            </div>
<div style="background-color:blue;padding:5px;margin:2px">
                <ng-content select="[name=footer]"></ng-content>
            </div>
        </div>
    `
})
class NgContentExampleComponent {}

//NgContemtAppComponent.ts
import { Component } from 'angular/core';
@Component({
    selector:'app',
    template:`
        <example-content>
            <header>Header content</header>
            <div class="class-select">div with .class-content</div>
            <div name="footer">Footer content</div>
        </example-content>
    `
})
export class NgContentAppComponent {}

組件生命周期

組件的生命周期由angular內部管理,從組件的創(chuàng)建、創(chuàng)建,到數(shù)據(jù)變動事件的觸發(fā),再到組件從DOM中移除,angular都提供了一系列鉤子。這些鉤子可以在這些事件觸發(fā)時,執(zhí)行相應的回調函數(shù)。

生命周期鉤子

鉤子的接口包含@angular/core中。每個接口都對應一個名為ng+接口名的方法。

class ExampleInitHook implements OnInit {
    constructor() {}
    ngOnInit() {
        console.log('OnInit');
    }
}

以下是組件常用的生命周期鉤子方法,angular會按以下的順序依次調用鉤子方法:

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

除此之外,有的組件還提供了自己特有的生命周期鉤子,例如路由有routerOnActivate鉤子。

ngOnChanges

ngOnChanges鉤子用來響應組件輸入值發(fā)生變化時觸發(fā)的事件。該方法接收一個SimpleChanges對象,包含當前值和變化前的值。該方法在ngOnInit之前,或者當數(shù)據(jù)綁定輸入屬性的值發(fā)生變化時觸發(fā)。
只要在組件里定義了ngOnChanges方法,在輸入數(shù)據(jù)發(fā)生變化時該方法就會被自動調用。這里的“輸入數(shù)據(jù)”指的是通過@Input裝飾器顯示指定的變量。

ngOnInit

ngOnInit鉤子用于數(shù)據(jù)綁定輸入屬性之后初始化組件。該鉤子方法會在第一次ngOnChanges之后被調用。
使用ngOnInit有兩個重要原因:

  • 組件構造后不久就要進行復雜的初始化
  • 需要在輸入屬性設置完成之后才構建組件

在組件中,經(jīng)常會使用ngOnInit獲取數(shù)據(jù)。

ngDoCheck

用于變化監(jiān)測,該鉤子方法會在每次變化監(jiān)測發(fā)生時被調用。
每一個變化監(jiān)測周期內,不管數(shù)據(jù)值是否發(fā)生了變化,ngDoCheck都會被調用。但要慎用,例如鼠標移動時會觸發(fā)mousemove事件,此時變化監(jiān)測會被頻繁觸發(fā),隨之ngDoCheck也會被頻繁調用。因此,ngDoCheck方法中不能寫復雜的代碼,否則性能會受影響。
絕大多數(shù)情況下,ngDoCheckngOnChanges不應該一起使用。ngOnChanges能做的事,ngDoCheck也能做到,而ngDoCheck監(jiān)測的力度更小,可完成更靈活的變化監(jiān)測邏輯。

ngAfterContentInit

在組件中使用<ng-content>將外部內容嵌入到組件視圖后就會調用ngAfterContentInit,它在第一次ngDoCheck執(zhí)行后調用,且只執(zhí)行一次。

ngAfterContentChecked

在組件使用了<ng-content>自定義內容的情況下,angular在這些外部內容嵌入到組件視圖后,或每次變化監(jiān)測的時候都會調用ngAfterContentChecked。

ngAfterViewInit

ngAfterViewInit會在angular創(chuàng)建了組件的視圖及其子視圖之后被調用。

ngAfterViewChecked

ngAfterViewChecked在angular創(chuàng)建了組件的視圖及其子組件視圖之后被調用一次,并且在每次子組件變化監(jiān)測時也會被調用。

ngOnDestroy

ngOnDestroy在銷毀指令/組件之前觸發(fā)。那些不會被垃圾回收器自動回收的資源(如已訂閱的觀察者事件、綁定過的DOM事件、通過setTimeoutsetInterval設置過的計時器等)都應當在ngOnDestroy中手動銷毀掉,從而避免發(fā)生內存泄漏等問題。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,763評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,238評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,823評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,604評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,339評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,713評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,712評論 3 445
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,893評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,448評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,201評論 3 357
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,397評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,944評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,631評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,033評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,321評論 1 293
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,128評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,347評論 2 377

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,818評論 18 139
  • 本文章是我最近在公司的一場內部分享的內容。我有個習慣就是每次分享都會先將要分享的內容寫成文章。所以這個文集也是用來...
    Awey閱讀 9,458評論 4 67
  • 今天我來談談學習的過程,學習是一個持續(xù)的過程,而且學習必須是一個不斷沖擊自己意識的一個過程,一個好的理論、理念,你...
    春曉育兒講堂閱讀 653評論 0 0
  • 今天經(jīng)緯實驗小學一年級(二)班的微信群信息不斷更新!寶爸寶媽們都積極參與討論明天學前培訓!想來,如果跟你談...
    周國景閱讀 244評論 0 1
  • 今日陽光普照 我的心情不在云霄 也不曾藏匿幽邃深谷 上學的路上 我踩著自己的步伐 找尋自己的節(jié)奏和感覺 口袋里的耳...
    阿琴姑娘閱讀 769評論 42 67