這篇文章主要介紹了angular10組件的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
公司主營(yíng)業(yè)務(wù):成都網(wǎng)站制作、成都做網(wǎng)站、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)公司推出沾益免費(fèi)做網(wǎng)站回饋大家。
html模板
typescript,定義行為
css組,可以引入多個(gè)css文件,因此可以在一個(gè)組件里面定義多個(gè)css文件
//從angular主模塊中引入Component(組件裝飾器或組件注解) import { Component } from '@angular/core'; //裝飾器中以json的形式聲明元數(shù)據(jù) @Component({ //它指定了一個(gè)叫的元素。 該元素是 index.html 文件里的一個(gè)占位符 //為什么這個(gè)組件跟入口index建立了聯(lián)系呢?因?yàn)槿肟趍ain.ts中綁定了主模塊為appModule selector: 'app-root', //在模板中找對(duì)應(yīng)的標(biāo)簽,找到后創(chuàng)建并插入該組件實(shí)例 templateUrl: './app.component.html', // html模板 styleUrls: ['./app.component.css'], // css樣式,可以引入多個(gè)css文件 // 這個(gè)屬性(內(nèi)聯(lián)模板)和templateUrl(外聯(lián)模板)二選一,template后面可以直接跟html字符串 // 注意在模板語(yǔ)法(反引號(hào))中是使用插值表達(dá)式,不能使用${}插入值 template: ` {{title}}
` }) //組件控制器,寫邏輯代碼的地方 export class AppComponent { title = 'myAngular'; //構(gòu)造函數(shù)可以用來(lái)進(jìn)行屬性的聲明和初始化語(yǔ)句 //在angular里面有個(gè)特別重要的點(diǎn)要記?。褐荒芡ㄟ^(guò)構(gòu)造函數(shù)注入依賴 constructor() {} }
安裝 Angular CLI (npm install -g @angular/cli)
建立一個(gè) Angular 項(xiàng)目 (ng new )
如果不滿足這兩個(gè)條件,請(qǐng)參考 搭建環(huán)境。
使用 Angular CLI 創(chuàng)建一個(gè)組件
ng generate component// 創(chuàng)建一個(gè)組件 ng g c // 縮寫
常用的創(chuàng)建組件的一些其他選項(xiàng)
ng g c--skip-tests // 創(chuàng)建一個(gè)組件,且不用安裝測(cè)試文件 ng g c --inline-style // 縮寫-s,內(nèi)聯(lián)樣式 ng g c --inline-template // 縮寫-t,內(nèi)聯(lián)模板 ng g c --module= // 指定創(chuàng)建的組件在哪個(gè)模塊引用,在多個(gè)模塊的項(xiàng)目中會(huì)用到
除了通過(guò)angular cli自動(dòng)生成組件外,也可以手動(dòng)創(chuàng)建組件(不推薦),這里不介紹。
在工作中經(jīng)常能夠用到的生命周期就兩個(gè)(ngOninit和ngOnDestroy),其他的生命周期很少用到;但是如果能夠掌握組件的生命周期,對(duì)angular會(huì)掌握的得更加深刻。
生命周期含義
當(dāng) Angular 實(shí)例化組件類并渲染組件視圖及其子視圖時(shí),組件實(shí)例的生命周期就開(kāi)始了。生命周期一直伴隨著變更檢測(cè),Angular 會(huì)檢查數(shù)據(jù)綁定屬性何時(shí)發(fā)生變化,并按需更新視圖和組件實(shí)例。當(dāng) Angular 銷毀組件實(shí)例并從 DOM 中移除它渲染的模板時(shí),生命周期就結(jié)束了。當(dāng) Angular 在執(zhí)行過(guò)程中創(chuàng)建、更新和銷毀實(shí)例時(shí),指令就有了類似的生命周期。
應(yīng)用:
你的應(yīng)用可以使用生命周期鉤子方法來(lái)觸發(fā)組件或指令生命周期中的關(guān)鍵事件,以初始化新實(shí)例,需要時(shí)啟動(dòng)變更檢測(cè),在變更檢測(cè)過(guò)程中響應(yīng)更新,并在刪除實(shí)例之前進(jìn)行清理。
如何實(shí)現(xiàn)生命周期事件
每個(gè)組件或指令都可以實(shí)現(xiàn)一個(gè)或多個(gè)生命周期鉤子,這些生命周期鉤子可以在適當(dāng)?shù)臅r(shí)候?qū)M件或指令實(shí)例進(jìn)行操作。
每個(gè)接口都有唯一的一個(gè)鉤子方法,它們的名字是由接口名再加上 ng 前綴構(gòu)成的。比如,OnInit 接口的鉤子方法叫做 ngOnInit()。如果你在組件或指令類中實(shí)現(xiàn)了這個(gè)方法,Angular 就會(huì)在首次檢查完組件或指令的輸入屬性后,緊接著調(diào)用它
import { Component } from '@angular/core'; @Component({ selector: 'app-root', styleUrls: ['./app.component.css'], template: `{{title}}
` }) // 實(shí)現(xiàn)OnInit生命周期,可以實(shí)現(xiàn)多個(gè)生命周期 export class AppComponent implements OnInit{ title = 'myAngular'; constructor() {} ngOnInit(){ console.log("Angular在首次檢查完組件的輸入屬性后,然后調(diào)用它,只調(diào)用一次") } }
生命周期概覽
鉤子 | 時(shí)機(jī) | 用途 | 注意 |
---|---|---|---|
ngOnChanges() | 當(dāng)被綁定的輸入屬性的值發(fā)生變化時(shí)調(diào)用,首次調(diào)用一定會(huì)發(fā)生在 ngOnInit() 之前 | 當(dāng) Angular 設(shè)置或重新設(shè)置數(shù)據(jù)綁定的輸入屬性時(shí)響應(yīng)。 該方法接受當(dāng)前和上一屬性值的 SimpleChanges 對(duì)象 | 這發(fā)生的非常頻繁,所以你在這里執(zhí)行的任何操作都會(huì)顯著影響性能。 |
ngOnInit() | 在第一輪 ngOnChanges() 完成之后調(diào)用,只調(diào)用一次。 | 在 Angular 第一次顯示數(shù)據(jù)綁定和設(shè)置指令/組件的輸入屬性之后,初始化指令/組件。組件獲取初始數(shù)據(jù)的好地方 | 很重要,只調(diào)用一次 |
ngDoCheck() | 緊跟在每次執(zhí)行變更檢測(cè)時(shí)的 ngOnChanges() 和 首次執(zhí)行變更檢測(cè)時(shí)的 ngOnInit() 后調(diào)用。 | 檢測(cè),并在發(fā)生 Angular 無(wú)法或不愿意自己檢測(cè)的變化時(shí)作出反應(yīng)。 | 它和ngOnChanges一樣發(fā)生的很頻繁 |
ngAfterContentInit() | 第一次 ngDoCheck() 之后調(diào)用,只調(diào)用一次。 | 當(dāng) Angular 把外部?jī)?nèi)容投影進(jìn)組件視圖或指令所在的視圖之后調(diào)用。 | 只調(diào)用一次 |
ngAfterContentChecked() | ngAfterContentInit() 和每次 ngDoCheck() 之后調(diào)用 | 每當(dāng) Angular 檢查完被投影到組件或指令中的內(nèi)容之后調(diào)用。 | |
ngAfterViewInit() | 第一次 ngAfterContentChecked() 之后調(diào)用,只調(diào)用一次。 | 初始化完組件視圖及其子視圖之后調(diào)用。 | 只調(diào)用一次 |
ngAfterViewChecked() | ngAfterViewInit() 和每次 ngAfterContentChecked() 之后調(diào)用。 | 每次做完組件視圖和子視圖的變更檢測(cè)之后調(diào)用。 | |
ngOnDestroy() | 在 Angular 銷毀指令/組件之前調(diào)用。 | 當(dāng) Angular 每次銷毀指令/組件之前調(diào)用并清掃。 在這兒反訂閱可觀察對(duì)象和分離事件處理器,以防內(nèi)存泄漏。 取消訂閱可觀察對(duì)象、 清除定時(shí)器、 反注冊(cè)該指令在全局或應(yīng)用服務(wù)中注冊(cè)過(guò)的所有回調(diào)。 | 很重要 |
重點(diǎn)生命周期詳解
初始化組件和指令 ngOnInit
在構(gòu)造函數(shù)外部執(zhí)行復(fù)雜的初始化。組件的構(gòu)造應(yīng)該既便宜又安全。比如,你不應(yīng)該在組件構(gòu)造函數(shù)中獲取數(shù)據(jù)。當(dāng)在測(cè)試中創(chuàng)建組件時(shí)或者決定顯示它之前,你不應(yīng)該擔(dān)心新組件會(huì)嘗試聯(lián)系遠(yuǎn)程服務(wù)器。ngOnInit() 是組件獲取初始數(shù)據(jù)的好地方。
在 Angular 設(shè)置好輸入屬性之后設(shè)置組件。構(gòu)造函數(shù)應(yīng)該只把初始局部變量設(shè)置為簡(jiǎn)單的值。請(qǐng)記住,只有在構(gòu)造完成之后才會(huì)設(shè)置指令的數(shù)據(jù)綁定輸入屬性。如果要根據(jù)這些屬性對(duì)指令進(jìn)行初始化,請(qǐng)?jiān)谶\(yùn)行 ngOnInit() 時(shí)設(shè)置它們
在實(shí)例銷毀時(shí)進(jìn)行清理 ngOnDestroy
這里是釋放資源的地方,這些資源不會(huì)自動(dòng)被垃圾回收。如果你不這樣做,就存在內(nèi)存泄漏的風(fēng)險(xiǎn)。
取消訂閱可觀察對(duì)象和 DOM 事件。
停止 interval 計(jì)時(shí)器。
反注冊(cè)該指令在全局或應(yīng)用服務(wù)中注冊(cè)過(guò)的所有回調(diào)。
ngOnDestroy() 方法也可以用來(lái)通知應(yīng)用程序的其它部分,該組件即將消失
頁(yè)面埋點(diǎn)
可以在組件中通過(guò)ngOnInit和ngOnDestroy方法統(tǒng)計(jì)頁(yè)面的時(shí)長(zhǎng),
更好的做法可以通過(guò)指令實(shí)現(xiàn)ngOnInit和ngOnDestroy生命周期,用來(lái)統(tǒng)計(jì)頁(yè)面時(shí)長(zhǎng)
也可以通過(guò)路由守衛(wèi)來(lái)記錄頁(yè)面出入棧所需要的時(shí)間
@Directive({selector: '[appSpy]'}) export class SpyDirective implements OnInit, OnDestroy { constructor(private logger: LoggerService) { } ngOnInit() { this.logIt(`onInit`); } ngOnDestroy() { this.logIt(`onDestroy`); } private logIt(msg: string) { this.logger.log(`Spy #${nextId++} ${msg}`); } }
使用變更檢測(cè)鉤子 ngOnchanges
一旦檢測(cè)到該組件或指令的輸入屬性發(fā)生了變化,Angular 就會(huì)調(diào)用它的 ngOnChanges() 方法。
因?yàn)檫@個(gè)方法會(huì)頻繁執(zhí)行,所以要注意判斷的計(jì)算量,會(huì)影響性能。
// 可以監(jiān)聽(tīng)輸入屬性的變化 ngOnChanges(changes: SimpleChanges) { for (const propName in changes) { const chng = changes[propName]; const cur = JSON.stringify(chng.currentValue); const prev = JSON.stringify(chng.previousValue); this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`); } }
一、父子組件的通信(基礎(chǔ))
父?jìng)髯?/strong>
1、父組件通過(guò)屬性綁定向子組件傳值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: `` }) export class ParentComponent { msg = '父組件傳的值'; }
2、子組件通過(guò)@Input接收數(shù)據(jù)
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: `{{msg}}
` }) export class ChildComponent { @Input() msg: String; }
子傳父
1、子組件通過(guò)自定義事件,向父組件發(fā)送數(shù)據(jù)
import { Component, Input, EventEmitter, Output} from '@angular/core'; , @Component({ selector: 'app-child', template: `{{msg}}
` }) export class ChildComponent { @Input() msg: String; @Output() voted = new EventEmitter(); vote() { this.voted.emit("子組件傳的值"); } }
2、父組件通過(guò)監(jiān)聽(tīng)自定義事件,接收子組件的傳值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: `` }) export class ParentComponent { msg = '父組件傳的值'; voted(val){ //監(jiān)聽(tīng)自定義事件的傳值 console.log(val) } }
子組件怎么監(jiān)聽(tīng)輸入屬性值的變化?(2種方法)
1、可以使用一個(gè)輸入屬性@Input()的 setter,以攔截父組件中值的變化。
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: '"{{name}}"
' }) export class ChildComponent { @Input() get name(): string { return this._name; } set name(name: string) { this._name = (name && name.trim()) || ''; } private _name = ''; }
2、通過(guò)ngOnChange()來(lái)截聽(tīng)輸入屬性值的變化
當(dāng)需要監(jiān)視多個(gè)、交互式輸入屬性的時(shí)候,本方法比用屬性的 setter 更合適。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-version-child', template: `Version {{major}}.{{minor}}
Change log:
父組件怎么讀取子組件的屬性和調(diào)用子組件的方法?(2種方法)
1、通過(guò)本地變量代表子組件
父組件不能使用數(shù)據(jù)綁定來(lái)讀取子組件的屬性或調(diào)用子組件的方法。但可以在父組件模板里,新建一個(gè)本地變量來(lái)代表子組件,然后利用這個(gè)變量來(lái)讀取子組件的屬性和調(diào)用子組件的方法,如下例所示。
思考:父組件可以通過(guò)這種方式讀取子組件的私有屬性和私有方法嗎?
父組件
import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; @Component({ selector: 'app-countdown-parent-lv', template: `Countdown to Liftoff (via local variable)
//調(diào)用子組件方法{{timer.seconds}}//讀取子組件屬性`, styleUrls: ['../assets/demo.css'] }) export class CountdownLocalVarParentComponent { }
子組件
import { Component, OnDestroy } from '@angular/core'; @Component({ selector: 'app-countdown-timer', template: '{{message}}
' }) export class CountdownTimerComponent implements OnDestroy { intervalId = 0; message = ''; seconds = 11; ngOnDestroy() { this.clearTimer(); } start() { this.countDown(); } stop() { this.clearTimer(); this.message = `Holding at T-${this.seconds} seconds`; } private clearTimer() { clearInterval(this.intervalId); } private countDown() { this.clearTimer(); this.intervalId = window.setInterval(() => { this.seconds -= 1; if (this.seconds === 0) { this.message = 'Blast off!'; } else { if (this.seconds < 0) { this.seconds = 10; } // reset this.message = `T-${this.seconds} seconds and counting`; } }, 1000); } }
2、父組件調(diào)用@viewChild() (基礎(chǔ),推薦使用)
這個(gè)本地變量方法是個(gè)簡(jiǎn)單便利的方法。但是它也有局限性(只能在模板html中使用),因?yàn)楦附M件-子組件的連接必須全部在父組件的模板中進(jìn)行。父組件本身的ts代碼對(duì)子組件沒(méi)有訪問(wèn)權(quán)。
當(dāng)父組件類需要訪問(wèn)子組件時(shí),可以把子組件作為 ViewChild,注入到父組件里面。
父組件類中訪問(wèn)子組件的屬性和方法:
import { AfterViewInit, ViewChild } from '@angular/core'; import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; //引入子組件 @Component({ selector: 'app-countdown-parent-vc', template: `Countdown to Liftoff (via ViewChild)
{{ seconds() }}`, styleUrls: ['../assets/demo.css'] }) export class CountdownViewChildParentComponent implements AfterViewInit { //通過(guò) @ViewChild 屬性裝飾器,將子組件 CountdownTimerComponent 注入到私有屬性 timerComponent 里面。 @ViewChild(CountdownTimerComponent) private timerComponent: CountdownTimerComponent; seconds() { return 0; } // angular創(chuàng)建了組件的子視圖后會(huì)調(diào)用它,注意獲取子組件的屬性,要在子組件視圖加載之后 ngAfterViewInit() { // 訪問(wèn)子組件屬性 setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0); } start() { this.timerComponent.start(); } // 訪問(wèn)子組件的方法 stop() { this.timerComponent.stop(); } }
注意:(使用場(chǎng)景很多,必須掌握)
ngAfterViewInit() 生命周期鉤子是非常重要的一步。被注入的計(jì)時(shí)器組件只有在 Angular 顯示了父組件視圖之后才能訪問(wèn),所以它先把秒數(shù)顯示為 0.
然后 Angular 會(huì)調(diào)用 ngAfterViewInit 生命周期鉤子,但這時(shí)候再更新父組件視圖的倒計(jì)時(shí)就已經(jīng)太晚了。Angular 的單向數(shù)據(jù)流規(guī)則會(huì)阻止在同一個(gè)周期內(nèi)更新父組件視圖。應(yīng)用在顯示秒數(shù)之前會(huì)被迫再等一輪。
使用 setTimeout() 來(lái)等下一輪,然后改寫 seconds() 方法,這樣它接下來(lái)就會(huì)從注入的這個(gè)計(jì)時(shí)器組件里獲取秒數(shù)的值。
二、組件通過(guò)服務(wù)來(lái)通信(發(fā)布訂閱者模式,基礎(chǔ),必須掌握)
父組件和它的子組件共享同一個(gè)服務(wù),利用該服務(wù)在組件家族內(nèi)部實(shí)現(xiàn)雙向通信。
不僅局限于父子組件,只要組件與組件共享同一個(gè)服務(wù),就可以實(shí)現(xiàn)數(shù)據(jù)通信。
父組件
父組件
子組件
子組件
//服務(wù)重點(diǎn) //meditor.service.ts import {Injectable} from '@angular/core'; import {Subject} from 'rxjs/Subject'; import {Observable} from 'rxjs/Observable'; @Injectable() export class MeditorService { private subject = new Subject(); constructor() {} // 獲取訂閱者 public getObservable(): Observable { return this.subject.asObservable(); } // 推送信息 public push(msg: MeditorMsg) { this.subject.next(msg); } } // 中間者信息 export interface MeditorMsg { id: string; body: any; }
subscription: Subscription = null; //初始化一個(gè)訂閱對(duì)象 //子組件構(gòu)造函數(shù),用于監(jiān)聽(tīng)數(shù)據(jù)推送 constructor(private meditor: MeditorService) { this.subscription = meditor.getObservable().subscribe( msg => { console.log(msg); if (msg.id === 'parent') { //id為parent,獲取父組件數(shù)據(jù) this.serviceInput = msg.body; } } ); } // 子組件將數(shù)據(jù)推送到中間著,給訂閱者 clickService() { this.meditor.push({id: 'parent', body: this.serviceInput}); } //父組件構(gòu)造函數(shù),用于監(jiān)聽(tīng)數(shù)據(jù)推送 constructor(private meditor: MeditorService) { this.subscription = meditor.getObservable().subscribe( msg => { console.log(msg); if (msg.id === 'child') { //id為child,獲取子組件數(shù)據(jù) this.serviceInput = msg.body; } } ); } // 父組件將數(shù)據(jù)推送到中間著,給訂閱者 clickService() { this.meditor.push({id: 'parent', body: this.serviceInput}); } // 注意:訂閱一個(gè)對(duì)象,就是在生命周期結(jié)束前,要取消訂閱。 ngOnDestroy() { this.subscription.unsubscribe(); }
思考: 這種發(fā)布訂閱者模式適合全局狀態(tài)管理嗎?
三、可以通過(guò)本地緩存來(lái)實(shí)現(xiàn)通信(Cookie,LocalStorage、SessionStorage)
// 目的是好維護(hù) // 項(xiàng)目當(dāng)中用到的頁(yè)面緩存,需要在這里進(jìn)行聲明;key-value保持一致 // 聲明規(guī)則,不同類型的緩存使用前綴 session_/ local_ / cookie_ // 動(dòng)態(tài)設(shè)置緩存不用在這里聲明,但是需要在key后面加'_noSetType_'標(biāo)識(shí) export const CatchNameType = { session_userInfo: 'session_userInfo', // 用戶信息 session_toekn: 'session_token', // token local_loginInfo: 'local_loginInfo', // 本地緩存用戶名密碼 }; import { Injectable } from '@angular/core'; // 定義這個(gè)類,主要是看全局定義了哪些本地緩存 import { CatchNameType } from './catch_namae_type'; // -------------------------------------------------------緩存工具類(三類方法) // Cookie (方法有:set/get/remove) // SStorage(sessionStorage) (方法有:set/get/remove/clear) // LStorage(localStorage) (方法有:set/get/remove/clear) @Injectable({ providedIn: 'root', }) export class Catch { // cookie public static Cookie = { /** * cookie 存貯 * @param key 屬性 * @param value 值 * @param String expire 過(guò)期時(shí)間,單位天 */ set(key: string, value: any, expire: any): void { if (Catch.is_set_catch_name_type(key)) { const d = new Date(); d.setDate(d.getDate() + expire); document.cookie = `${key}=${value};expires=${d.toDateString()}`; } }, get(key: string): string { const cookieStr = unescape(document.cookie); const arr = cookieStr.split('; '); let cookieValue = ''; // tslint:disable-next-line: prefer-for-of for (let i = 0; i < arr.length; i++) { const temp = arr[i].split('='); if (temp[0] === key) { cookieValue = temp[1]; break; } } return cookieValue; }, remove(key: string): void { document.cookie = `${encodeURIComponent(key)}=;expires=${new Date()}`; }, }; // sessionStorage public static SStorage = { set(key: string, value: any): void { if (Catch.is_set_catch_name_type(key)) { sessionStorage.setItem(key, JSON.stringify(value)); } }, get(key: string): any { const jsonString = sessionStorage.getItem(key) === 'undefined' ? undefined : sessionStorage.getItem(key); return jsonString ? JSON.parse(jsonString) : null; }, remove(key: string): void { sessionStorage.removeItem(key); }, clear(): void { sessionStorage.clear(); }, }; // localStorage public static LStorage = { set(key: string, value: any): void { if (Catch.is_set_catch_name_type(key)) { localStorage.setItem(key, JSON.stringify(value)); } }, get(key: string): any { const jsonString = localStorage.getItem(key) === 'undefined' ? undefined : localStorage.getItem(key); return jsonString ? JSON.parse(jsonString) : null; }, remove(key: string): void { localStorage.removeItem(key); }, clear(): void { localStorage.clear(); }, }; // 設(shè)置緩存的時(shí)候是否在catch_name_type里面聲明 static is_set_catch_name_type(key: string): boolean { let allow = false; // 對(duì)動(dòng)態(tài)設(shè)置緩存不進(jìn)行檢查 if (key.indexOf('_noSetType_') !== -1) { allow = true; console.log('動(dòng)態(tài)設(shè)置緩存', key); return allow; } // 對(duì)命名規(guī)則進(jìn)行檢查 const nameRule = key.indexOf('session_') !== -1 || key.indexOf('local_') !== -1 || key.indexOf('cookie_') !== -1; if (!nameRule) { allow = false; console.log('命名規(guī)則錯(cuò)誤', key); return allow; } // 靜態(tài)設(shè)置的緩存需要配置類型 Object.values(CatchNameType).forEach((item) => { if (item === key) { allow = true; } }); if (!allow) { console.log('緩存操作失敗,請(qǐng)檢查配置緩存類型'); } return allow; } }
四、頁(yè)面路由傳參也可以實(shí)現(xiàn)單向通信
這部分內(nèi)容,我會(huì)在路由章節(jié)整理。
組件通信總結(jié)
所以組件通信大概有如下幾種:
1、父子組件通信(1、@Input() @output 2、本地變量#val 3、@viewChild())
2、通過(guò)服務(wù)
3、頁(yè)面緩存
4、頁(yè)面級(jí)組件傳參(兩個(gè)頁(yè)面等同于兩個(gè)組件)
組件的模板不會(huì)永遠(yuǎn)是固定的。應(yīng)用可能會(huì)需要在運(yùn)行期間按需加載一些新的組件。 通過(guò)下面的例子可以了解動(dòng)態(tài)組件的基本使用
1、創(chuàng)建組件,被引入的組件
@Component({
template: `hello world`
})
export class DynamicComponent { }
2、創(chuàng)建容器組件,用于加載動(dòng)態(tài)組件
@Component({ selector: 'app-container', template: ` ` }) export class AppContainerComponent { // 聲明容器 @ViewChild("dynamicContainer", { read: ViewContainerRef }) container: ViewContainerRef; }
在AppContainerComponent組件中,通過(guò)@ViewChild裝飾器來(lái)獲取視圖中的模板元素,如果沒(méi)有指定第二個(gè)查詢參數(shù),則默認(rèn)返回 組件實(shí)例或相應(yīng)的DOM元素,但這個(gè)示例中,我們需要獲取ViewContainerRef實(shí)例也就是視圖容器。可以在視圖容器中創(chuàng)建、插入、刪除組件等。
3、動(dòng)態(tài)創(chuàng)建組件
在創(chuàng)建組件之前,需要注入ComponentFactoryResolver服務(wù)對(duì)象,該服務(wù)是動(dòng)態(tài)加載組件的核心,可以將一個(gè)組件實(shí)例呈現(xiàn)到另一個(gè) 組件視圖上。
使用ComponentFactoryResolve將已聲明但未實(shí)例化的組件解析成為可以動(dòng)態(tài)加載的component
//依賴組件類型獲取對(duì)應(yīng)的factory,從名字上可以看出該factory是用來(lái)初始化組件的 const componentFactory = this.ComponentFactoryResolver(DynamicComponent); //調(diào)用視圖容器的createComponent方法并將組件添加到容器上。該方法內(nèi)部會(huì)調(diào)用factory的create方法來(lái)初始化組件。 const modalContainerRef = this.container.createComponent(componentFactory);
4、為組件屬性賦值
通過(guò)如下的方式為組件屬性進(jìn)行賦值
modalContainerRef.instance.property = ***;
5、銷毀組件
在使用組件后,記得要銷毀組件。
modalContainerRef.destroy();
6、組件注冊(cè)
為了能夠動(dòng)態(tài)創(chuàng)建組件需要將組件在模塊的entryComponents中聲明。因?yàn)樵趀ntryComponents中聲明的組件Angular都會(huì)創(chuàng)建一個(gè) ComponentFactory并將其存儲(chǔ)在ComponentFactoryResolver中,這是動(dòng)態(tài)加載必需的步驟。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“angular10組件的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!