這篇文章主要為大家展示了“Angular 4依賴注入之Injectable裝飾器的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Angular 4依賴注入之Injectable裝飾器的示例分析”這篇文章吧。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:申請(qǐng)域名、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、桂陽網(wǎng)站維護(hù)、網(wǎng)站推廣。
開發(fā)環(huán)境及開發(fā)語言:
Angular 4 +
Angular CLI
TypeScript
基礎(chǔ)知識(shí)
裝飾器是什么
它是一個(gè)表達(dá)式
該表達(dá)式被執(zhí)行后,返回一個(gè)函數(shù)
函數(shù)的入?yún)⒎謩e為 targe、name 和 descriptor
執(zhí)行該函數(shù)后,可能返回 descriptor 對(duì)象,用于配置 target 對(duì)象
裝飾器的分類
類裝飾器 (Class decorators)
屬性裝飾器 (Property decorators)
方法裝飾器 (Method decorators)
參數(shù)裝飾器 (Parameter decorators)
TypeScript 類裝飾器
類裝飾器聲明:
declare type ClassDecorator =(target: TFunction) => TFunction | void
類裝飾器顧名思義,就是用來裝飾類的。它接收一個(gè)參數(shù):
target: TFunction - 被裝飾的類
看完第一眼后,是不是感覺都不好了。沒事,我們馬上來個(gè)例子:
function Greeter(target: Function): void { target.prototype.greet = function (): void { console.log('Hello!'); } } @Greeter class Greeting { constructor() { // 內(nèi)部實(shí)現(xiàn) } } let myGreeting = new Greeting(); myGreeting.greet(); // console output: 'Hello!';
上面的例子中,我們定義了 Greeter 類裝飾器,同時(shí)我們使用了 @Greeter 語法,來使用裝飾器。
Injectable 類裝飾器使用
import { Injectable } from '@angular/core'; @Injectable() class HeroService {}
Injectable 裝飾器
在介紹 Injectable 裝飾器前,我們先來回顧一下 HeroComponent 組件:
@Component({ selector: 'app-hero', template: `
在 HeroComponent 組件的 ngOnInit 生命周期鉤子中,我們?cè)讷@取英雄信息前輸出相應(yīng)的調(diào)試信息。其實(shí)為了避免在每個(gè)應(yīng)用的組件中都添加 log 語句,我們可以把 log 語句放在 getHeros() 方法內(nèi)。
更新前 HeroService 服務(wù)
export class HeroService { heros: Array<{ id: number; name: string }> = [ { id: 11, name: 'Mr. Nice' }, { id: 12, name: 'Narco' }, { id: 13, name: 'Bombasto' }, { id: 14, name: 'Celeritas' }, { id: 15, name: 'Magneta' }, { id: 16, name: 'RubberMan' }, { id: 17, name: 'Dynama' }, { id: 18, name: 'Dr IQ' }, { id: 19, name: 'Magma' }, { id: 20, name: 'Tornado' } ]; getHeros() { return this.heros; } }
更新后 HeroService 服務(wù)
import { LoggerService } from './logger.service'; export class HeroService { constructor(private loggerService: LoggerService) { } heros: Array<{ id: number; name: string }> = [ { id: 11, name: 'Mr. Nice' }, { id: 12, name: 'Narco' }, { id: 13, name: 'Bombasto' }, { id: 14, name: 'Celeritas' }, { id: 15, name: 'Magneta' } ]; getHeros() { this.loggerService.log('Fetching heros...'); return this.heros; } }
當(dāng)以上代碼運(yùn)行后會(huì)拋出以下異常信息:
Uncaught Error: Can't resolve all parameters for HeroService: (?).
上面異常信息說明無法解析 HeroService 的所有參數(shù),而 HeroService 服務(wù)的構(gòu)造函數(shù)如下:
export class HeroService { constructor(private loggerService: LoggerService) { } }
該構(gòu)造函數(shù)的輸入?yún)?shù)是 loggerService 且它的類型是 LoggerService 。在繼續(xù)深入研究之前,我們來看一下 HeroService 最終生成的 ES5 代碼:
var HeroService = (function() { function HeroService(loggerService) { this.loggerService = loggerService; this.heros = [{...}, ...]; } HeroService.prototype.getHeros = function() { this.loggerService.log('Fetching heros...'); return this.heros; }; return HeroService; }());
我們發(fā)現(xiàn)生成的 ES5 代碼中,HeroService 構(gòu)造函數(shù)中是沒有包含任何類型信息的,因此 Angular Injector (注入器) 就無法正常工作了。那么要怎么保存 HeroService 類構(gòu)造函數(shù)中參數(shù)的類型信息呢?相信你已經(jīng)想到了答案 — 當(dāng)然是使用 Injectable 裝飾器咯。接下來我們更新一下 HeroService:
import { Injectable } from '@angular/core'; import { LoggerService } from './logger.service'; @Injectable() export class HeroService { // ... }
更新完上面的代碼,成功保存后,在 http://localhost:4200/ 頁面,你將看到熟悉的 "身影":
ID: 11 - Name: Mr. Nice ID: 12 - Name: Narco ID: 13 - Name: Bombasto ID: 14 - Name: Celeritas ID: 15 - Name: Magneta
現(xiàn)在我們?cè)賮砜匆幌?HeroService 類生成的 ES5 代碼:
var HeroService = (function() { function HeroService(loggerService) { this.loggerService = loggerService; this.heros = [{...}, ...]; } HeroService.prototype.getHeros = function() { this.loggerService.log('Fetching heros...'); return this.heros; }; return HeroService; }()); HeroService = __decorate([__webpack_require__.i( __WEBPACK_IMPORTED_MODULE_0__angular_core__["c"/* Injectable */ ])(), __metadata("design:paramtypes", ...)], HeroService);
__decorate 函數(shù)
var __decorate = (this && this.__decorate) || function(decorators, target, key, desc) {...};
__metadata 函數(shù)
var __metadata = (this && this.__metadata) || function(k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); };
我們發(fā)現(xiàn)相比未使用 Injectable 裝飾器,HeroService 服務(wù)生成的 ES5 代碼多出了 HeroService = __decorate(...)
這些代碼。簡(jiǎn)單起見,我稍微介紹一下,通過 Injectable 裝飾器,在編譯時(shí)會(huì)把 HeroService 服務(wù)構(gòu)造函數(shù)中參數(shù)的類型信息,通過 Reflect API 保存在 window['__core-js_shared__']
對(duì)象的內(nèi)部屬性中。當(dāng) Injector 創(chuàng)建 HeroService 對(duì)象時(shí),會(huì)通過 Reflect API 去讀取之前已保存的構(gòu)造函數(shù)中參數(shù)的類型信息,進(jìn)而正確的完成實(shí)例化操作。
我有話說
@Injectable() 是必須的么?
如果所創(chuàng)建的服務(wù)不依賴于其他對(duì)象,是可以不用使用 Injectable 類裝飾器。但當(dāng)該服務(wù)需要在構(gòu)造函數(shù)中注入依賴對(duì)象,就需要使用 Injectable 裝飾器。不過比較推薦的做法不管是否有依賴對(duì)象,在創(chuàng)建服務(wù)時(shí)都使用 Injectable 類裝飾器。
以上是“Angular 4依賴注入之Injectable裝飾器的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!