Angular 4依賴注入學(xué)習(xí)教程之Injectable裝飾器(六)
學(xué)習(xí)目錄
- Angular 4 依賴注入教程之一 依賴注入簡介
- Angular 4 依賴注入教程之二 組件服務(wù)注入
- Angular 4 依賴注入教程之三 ClassProvider的使用
- Angular 4 依賴注入教程之四 FactoryProvider的使用
- Angular 4 依賴注入教程之五 FactoryProvider配置依賴對象
- Angular 4 依賴注入教程之六 Injectable 裝飾器
- Angular 4 依賴注入教程之七 ValueProvider的使用
- Angular 4 依賴注入教程之八 InjectToken的使用
本文主要給大家介紹的是關(guān)于Angular 4依賴注入之Injectable裝飾器的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),下面來看看詳細的介紹:
本系列教程的開發(fā)環(huán)境及開發(fā)語言:
基礎(chǔ)知識
裝飾器是什么
- 它是一個表達式
- 該表達式被執(zhí)行后,返回一個函數(shù)
- 函數(shù)的入?yún)⒎謩e為 targe、name 和 descriptor
- 執(zhí)行該函數(shù)后,可能返回 descriptor 對象,用于配置 target 對象
裝飾器的分類
- 類裝飾器 (Class decorators)
- 屬性裝飾器 (Property decorators)
- 方法裝飾器 (Method decorators)
- 參數(shù)裝飾器 (Parameter decorators)
TypeScript 類裝飾器
類裝飾器聲明:
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void
類裝飾器顧名思義,就是用來裝飾類的。它接收一個參數(shù):
target: TFunction - 被裝飾的類
看完第一眼后,是不是感覺都不好了。沒事,我們馬上來個例子:
function Greeter(target: Function): void {
target.prototype.greet = function (): void {
console.log('Hello!');
}
}
@Greeter
class Greeting {
constructor() { // 內(nèi)部實現(xiàn) }
}
let myGreeting = new Greeting();
myGreeting.greet(); // console output: 'Hello!';
上面的例子中,我們定義了 Greeter 類裝飾器,同時我們使用了 @Greeter 語法,來使用裝飾器。
Injectable 類裝飾器使用
import { Injectable } from '@angular/core';
@Injectable()
class HeroService {}
Injectable 裝飾器
在介紹 Injectable 裝飾器前,我們先來回顧一下 HeroComponent 組件:
@Component({
selector: 'app-hero',
template: `
<ul>
<li *ngFor="let hero of heros">
ID: {{hero.id}} - Name: {{hero.name}}
</li>
</ul>
`
})
export class HeroComponent implements OnInit {
heros: Array<{ id: number; name: string }>;
constructor(private heroService: HeroService,
private loggerService: LoggerService) { }
ngOnInit() {
this.loggerService.log('Fetching heros...');
this.heros = this.heroService.getHeros();
}
}
在 HeroComponent 組件的 ngOnInit 生命周期鉤子中,我們在獲取英雄信息前輸出相應(yīng)的調(diào)試信息。其實為了避免在每個應(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)以上代碼運行后會拋出以下異常信息:
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)在我們再來看一下 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(...) 這些代碼。簡單起見,我稍微介紹一下,通過 Injectable 裝飾器,在編譯時會把 HeroService 服務(wù)構(gòu)造函數(shù)中參數(shù)的類型信息,通過 Reflect API 保存在 window['__core-js_shared__'] 對象的內(nèi)部屬性中。當(dāng) Injector 創(chuàng)建 HeroService 對象時,會通過 Reflect API 去讀取之前已保存的構(gòu)造函數(shù)中參數(shù)的類型信息,進而正確的完成實例化操作。
我有話說
@Injectable() 是必須的么?
如果所創(chuàng)建的服務(wù)不依賴于其他對象,是可以不用使用 Injectable 類裝飾器。但當(dāng)該服務(wù)需要在構(gòu)造函數(shù)中注入依賴對象,就需要使用 Injectable 裝飾器。不過比較推薦的做法不管是否有依賴對象,在創(chuàng)建服務(wù)時都使用 Injectable 類裝飾器。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者使用Angular 4能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
angularjs使用div模擬textarea文本框的方法
今天小編就為大家分享一篇angularjs使用div模擬textarea文本框的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10
angularJS?實現(xiàn)長按不觸發(fā)點擊事件可以復(fù)制剪貼方法
這篇文章主要為大家介紹了angularJS實現(xiàn)長按不觸發(fā)點擊事件可以復(fù)制剪貼方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06
Angular.js實現(xiàn)多個checkbox只能選擇一個的方法示例
這篇文章主要給大家介紹了利用Angular.js實現(xiàn)多個checkbox只能選擇一個的方法,文中給出了詳細的示例代碼,相信對大家具有一定的參考價值,下面來一起看看吧。2017-02-02
AngularJS實現(xiàn)根據(jù)變量改變動態(tài)加載模板的方法
這篇文章主要介紹了AngularJS實現(xiàn)根據(jù)變量改變動態(tài)加載模板的方法,結(jié)合實例形式簡單分析了AngularJS動態(tài)加載模板的主要操作技巧與模板實現(xiàn)代碼,需要的朋友可以參考下2016-11-11
詳談Angular 2+ 的表單(一)之模板驅(qū)動型表單
這篇文章主要介紹了Angular 2+ 的表單(一)之模板驅(qū)動型表單,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04
解決angular的$http.post()提交數(shù)據(jù)時后臺接收不到參數(shù)值問題的方法
這篇文章為大家分享了解決angular的$http.post()提交數(shù)據(jù)時后臺接收不到參數(shù)值問題的方法,感興趣的小伙伴們可以參考一下2015-12-12

