您好,登錄后才能下訂單哦!
這篇文章主要介紹了angular10組件的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
html模板
typescript,定義行為
css組,可以引入多個(gè)css文件,因此可以在一個(gè)組件里面定義多個(gè)css文件
//從angular主模塊中引入Component(組件裝飾器或組件注解) import { Component } from '@angular/core'; //裝飾器中以json的形式聲明元數(shù)據(jù) @Component({ //它指定了一個(gè)叫 <app-root> 的元素。 該元素是 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字符串 // 注意在模板語法(反引號(hào))中是使用插值表達(dá)式,不能使用${}插入值 template: `<h2>{{title}}</h2>` }) //組件控制器,寫邏輯代碼的地方 export class AppComponent { title = 'myAngular'; //構(gòu)造函數(shù)可以用來進(jìn)行屬性的聲明和初始化語句 //在angular里面有個(gè)特別重要的點(diǎn)要記住:只能通過構(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 <project-name> // 創(chuàng)建一個(gè)組件 ng g c <project-name> // 縮寫
常用的創(chuàng)建組件的一些其他選項(xiàng)
ng g c <project-name> --skip-tests // 創(chuàng)建一個(gè)組件,且不用安裝測(cè)試文件 ng g c <project-name> --inline-style // 縮寫-s,內(nèi)聯(lián)樣式 ng g c <project-name> --inline-template // 縮寫-t,內(nèi)聯(lián)模板 ng g c <project-name> --module= <module-name> // 指定創(chuàng)建的組件在哪個(gè)模塊引用,在多個(gè)模塊的項(xiàng)目中會(huì)用到
除了通過angular cli自動(dòng)生成組件外,也可以手動(dòng)創(chuàng)建組件(不推薦),這里不介紹。
在工作中經(jīng)常能夠用到的生命周期就兩個(gè)(ngOninit和ngOnDestroy),其他的生命周期很少用到;但是如果能夠掌握組件的生命周期,對(duì)angular會(huì)掌握的得更加深刻。
生命周期含義
當(dāng) Angular 實(shí)例化組件類并渲染組件視圖及其子視圖時(shí),組件實(shí)例的生命周期就開始了。生命周期一直伴隨著變更檢測(cè),Angular 會(huì)檢查數(shù)據(jù)綁定屬性何時(shí)發(fā)生變化,并按需更新視圖和組件實(shí)例。當(dāng) Angular 銷毀組件實(shí)例并從 DOM 中移除它渲染的模板時(shí),生命周期就結(jié)束了。當(dāng) Angular 在執(zhí)行過程中創(chuàng)建、更新和銷毀實(shí)例時(shí),指令就有了類似的生命周期。
應(yīng)用:
你的應(yīng)用可以使用生命周期鉤子方法來觸發(fā)組件或指令生命周期中的關(guān)鍵事件,以初始化新實(shí)例,需要時(shí)啟動(dòng)變更檢測(cè),在變更檢測(cè)過程中響應(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: `<h2>{{title}}</h2>` }) // 實(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 無法或不愿意自己檢測(cè)的變化時(shí)作出反應(yīng)。 | 它和ngOnChanges一樣發(fā)生的很頻繁 |
ngAfterContentInit() | 第一次 ngDoCheck() 之后調(diào)用,只調(diào)用一次。 | 當(dāng) Angular 把外部內(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è)過的所有回調(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è)置為簡單的值。請(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è)過的所有回調(diào)。
ngOnDestroy() 方法也可以用來通知應(yīng)用程序的其它部分,該組件即將消失
頁面埋點(diǎn)
可以在組件中通過ngOnInit和ngOnDestroy方法統(tǒng)計(jì)頁面的時(shí)長,
更好的做法可以通過指令實(shí)現(xiàn)ngOnInit和ngOnDestroy生命周期,用來統(tǒng)計(jì)頁面時(shí)長
也可以通過路由守衛(wèi)來記錄頁面出入棧所需要的時(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)聽輸入屬性的變化 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ǔ))
父傳子
1、父組件通過屬性綁定向子組件傳值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: ` <app-child [msg]="msg"></app-child> ` }) export class ParentComponent { msg = '父組件傳的值'; }
2、子組件通過@Input接收數(shù)據(jù)
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: ` <p>{{msg}}</p> ` }) export class ChildComponent { @Input() msg: String; }
子傳父
1、子組件通過自定義事件,向父組件發(fā)送數(shù)據(jù)
import { Component, Input, EventEmitter, Output} from '@angular/core'; , @Component({ selector: 'app-child', template: ` <p>{{msg}}</p> <button (click)="vote()" >發(fā)送</button> ` }) export class ChildComponent { @Input() msg: String; @Output() voted = new EventEmitter<boolean>(); vote() { this.voted.emit("子組件傳的值"); } }
2、父組件通過監(jiān)聽自定義事件,接收子組件的傳值
import { Component } from '@angular/core'; @Component({ selector: 'app-parent', template: ` <app-child [msg]="msg" (voted)="voted($event)"></app-child> ` }) export class ParentComponent { msg = '父組件傳的值'; voted(val){ //監(jiān)聽自定義事件的傳值 console.log(val) } }
子組件怎么監(jiān)聽輸入屬性值的變化?(2種方法)
1、可以使用一個(gè)輸入屬性@Input()的 setter,以攔截父組件中值的變化。
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-child', template: '<h4>"{{name}}"</h4>' }) export class ChildComponent { @Input() get name(): string { return this._name; } set name(name: string) { this._name = (name && name.trim()) || '<no name set>'; } private _name = ''; }
2、通過ngOnChange()來截聽輸入屬性值的變化
當(dāng)需要監(jiān)視多個(gè)、交互式輸入屬性的時(shí)候,本方法比用屬性的 setter 更合適。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; @Component({ selector: 'app-version-child', template: ` <h4>Version {{major}}.{{minor}}</h4> <h5>Change log:</h5> <ul> <li *ngFor="let change of changeLog">{{change}}</li> </ul> ` }) export class VersionChildComponent implements OnChanges { @Input() major: number; @Input() minor: number; changeLog: string[] = []; ngOnChanges(changes: SimpleChanges) { //ngOnchange適合監(jiān)聽子組件多個(gè)輸入屬性的變化 const log: string[] = []; for (const propName in changes) { const changedProp = changes[propName]; const to = JSON.stringify(changedProp.currentValue); if (changedProp.isFirstChange()) { log.push(`Initial value of ${propName} set to ${to}`); } else { const from = JSON.stringify(changedProp.previousValue); log.push(`${propName} changed from ${from} to ${to}`); } } this.changeLog.push(log.join(', ')); } }
父組件怎么讀取子組件的屬性和調(diào)用子組件的方法?(2種方法)
1、通過本地變量代表子組件
父組件不能使用數(shù)據(jù)綁定來讀取子組件的屬性或調(diào)用子組件的方法。但可以在父組件模板里,新建一個(gè)本地變量來代表子組件,然后利用這個(gè)變量來讀取子組件的屬性和調(diào)用子組件的方法,如下例所示。
思考:父組件可以通過這種方式讀取子組件的私有屬性和私有方法嗎?
父組件
import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; @Component({ selector: 'app-countdown-parent-lv', template: ` <h4>Countdown to Liftoff (via local variable)</h4> <button (click)="timer.start()">Start</button> //調(diào)用子組件方法 <button (click)="timer.stop()">Stop</button> <div class="seconds">{{timer.seconds}}</div> //讀取子組件屬性 <app-countdown-timer #timer></app-countdown-timer> `, styleUrls: ['../assets/demo.css'] }) export class CountdownLocalVarParentComponent { }
子組件
import { Component, OnDestroy } from '@angular/core'; @Component({ selector: 'app-countdown-timer', template: '<p>{{message}}</p>' }) 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è)簡單便利的方法。但是它也有局限性(只能在模板html中使用),因?yàn)楦附M件-子組件的連接必須全部在父組件的模板中進(jìn)行。父組件本身的ts代碼對(duì)子組件沒有訪問權(quán)。
當(dāng)父組件類需要訪問子組件時(shí),可以把子組件作為 ViewChild,注入到父組件里面。
父組件類中訪問子組件的屬性和方法:
import { AfterViewInit, ViewChild } from '@angular/core'; import { Component } from '@angular/core'; import { CountdownTimerComponent } from './countdown-timer.component'; //引入子組件 @Component({ selector: 'app-countdown-parent-vc', template: ` <h4>Countdown to Liftoff (via ViewChild)</h4> <button (click)="start()">Start</button> <button (click)="stop()">Stop</button> <div class="seconds">{{ seconds() }}</div> <app-countdown-timer></app-countdown-timer> `, styleUrls: ['../assets/demo.css'] }) export class CountdownViewChildParentComponent implements AfterViewInit { //通過 @ViewChild 屬性裝飾器,將子組件 CountdownTimerComponent 注入到私有屬性 timerComponent 里面。 @ViewChild(CountdownTimerComponent) private timerComponent: CountdownTimerComponent; seconds() { return 0; } // angular創(chuàng)建了組件的子視圖后會(huì)調(diào)用它,注意獲取子組件的屬性,要在子組件視圖加載之后 ngAfterViewInit() { // 訪問子組件屬性 setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0); } start() { this.timerComponent.start(); } // 訪問子組件的方法 stop() { this.timerComponent.stop(); } }
注意:(使用場(chǎng)景很多,必須掌握)
ngAfterViewInit() 生命周期鉤子是非常重要的一步。被注入的計(jì)時(shí)器組件只有在 Angular 顯示了父組件視圖之后才能訪問,所以它先把秒數(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() 來等下一輪,然后改寫 seconds() 方法,這樣它接下來就會(huì)從注入的這個(gè)計(jì)時(shí)器組件里獲取秒數(shù)的值。
二、組件通過服務(wù)來通信(發(fā)布訂閱者模式,基礎(chǔ),必須掌握)
父組件和它的子組件共享同一個(gè)服務(wù),利用該服務(wù)在組件家族內(nèi)部實(shí)現(xiàn)雙向通信。
不僅局限于父子組件,只要組件與組件共享同一個(gè)服務(wù),就可以實(shí)現(xiàn)數(shù)據(jù)通信。
<!--parent.component.html--> <p style="width: 1000px;margin: auto"> <p class="card" style="width: 500px;float: left"> <p class="card-header"> 父組件</p> <p class="card-body"> <h6 class="card-title">父組件</h6> <p class="form-group"> <label for="serviceoutput">父組件服務(wù)輸入:</label> <input type="text" class="form-control" id="serviceoutput" placeholder="服務(wù)輸入" [(ngModel)]="serviceInput" > </p> <button class="btn btn-primary" (click)="clickService()">Service方式</button> </p> </p> <app-child></app-child> </p>
<!--child.component.html--> <p class="card" style="width: 500px;"> <p class="card-header">子組件</p> <p class="card-body"> <h6 class="card-title">子組件</h6> <p class="form-group"> <label for="serviceoutput">子組件服務(wù)輸入:</label> <input type="text" class="form-control" id="serviceoutput" placeholder="服務(wù)輸入" [(ngModel)]="serviceInput" > </p> <button class="btn btn-primary" (click)="clickService()">Service方式</button> </p> </p>
//服務(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<MeditorMsg>(); constructor() {} // 獲取訂閱者 public getObservable(): Observable<MeditorMsg> { 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)聽數(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)聽數(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)管理嗎?
三、可以通過本地緩存來實(shí)現(xiàn)通信(Cookie,LocalStorage、SessionStorage)
<!-- catch_namae_type.ts --> // 目的是好維護(hù) // 項(xiàng)目當(dāng)中用到的頁面緩存,需要在這里進(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', // 本地緩存用戶名密碼 }; <!--catch.ts--> 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 過期時(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; } }
四、頁面路由傳參也可以實(shí)現(xiàn)單向通信
這部分內(nèi)容,我會(huì)在路由章節(jié)整理。
組件通信總結(jié)
所以組件通信大概有如下幾種:
1、父子組件通信(1、@Input() @output 2、本地變量#val 3、@viewChild())
2、通過服務(wù)
3、頁面緩存
4、頁面級(jí)組件傳參(兩個(gè)頁面等同于兩個(gè)組件)
組件的模板不會(huì)永遠(yuǎn)是固定的。應(yīng)用可能會(huì)需要在運(yùn)行期間按需加載一些新的組件。 通過下面的例子可以了解動(dòng)態(tài)組件的基本使用
1、創(chuàng)建組件,被引入的組件
@Component({ template: `<span>hello world</span>` }) export class DynamicComponent { }
2、創(chuàng)建容器組件,用于加載動(dòng)態(tài)組件
@Component({ selector: 'app-container', template: ` <div #dynamicContainer></div> <button (click)="createComponent()">Create</button> ` }) export class AppContainerComponent { // 聲明容器 @ViewChild("dynamicContainer", { read: ViewContainerRef }) container: ViewContainerRef; }
在AppContainerComponent組件中,通過@ViewChild裝飾器來獲取視圖中的模板元素,如果沒有指定第二個(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是用來初始化組件的 const componentFactory = this.ComponentFactoryResolver(DynamicComponent); //調(diào)用視圖容器的createComponent方法并將組件添加到容器上。該方法內(nèi)部會(huì)調(diào)用factory的create方法來初始化組件。 const modalContainerRef = this.container.createComponent(componentFactory);
4、為組件屬性賦值
通過如下的方式為組件屬性進(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í)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。