摘要:只需引入一次的什么是項(xiàng)目中只需要引入一次的舉個(gè)例子,全局錯(cuò)誤處理根路由數(shù)據(jù)預(yù)加載請(qǐng)求攔截器等。更漂亮的是為我們提供了攔截器接口,我們只管開發(fā)攔截器邏輯功能,調(diào)用及使用全部控制權(quán)都在框架內(nèi)。
...
過了一遍 Angular 文檔 的小伙伴大致都會(huì)記得最佳實(shí)踐中提到過的有關(guān)CoreModule的一些解釋和說明,其實(shí)關(guān)于名字的命名不是強(qiáng)制性的,只要團(tuán)隊(duì)中一致 pass,你把它命名為XXXModule都無所謂。但是最主要的,還是我們需要理解“core”的作用以及在項(xiàng)目中發(fā)揮更好的作用和地位。
我記錄下我項(xiàng)目中對(duì)“core”的一些拙略見解和搭配。
core目錄縱觀整個(gè)Angular項(xiàng)目結(jié)構(gòu)以及最佳實(shí)踐,我們通常把項(xiàng)目按功能劃分文件夾,比如工具、共享、全局核心、頁(yè)面模塊組件、公用模塊組件等等,“core”在這里相當(dāng)于全局核心類型的范圍,那全局核心類型到底是聚集了項(xiàng)目的哪些功能呢?我的理解是我們可以把 全局單例服務(wù)、只需要引入一次 的東西都?xì)w并到這里。
全局單例服務(wù):這些服務(wù)在整個(gè)應(yīng)用生命周期內(nèi)只存在一個(gè)實(shí)例,也就是數(shù)據(jù)是全局互通的,而在 Angular 中實(shí)現(xiàn)單例服務(wù)就需要一個(gè)中間提供商(module)來做中介,也就是所謂的“CoreModule”,然后在根模塊引用一次便可全局使用,這也是官方推薦的一種單例服務(wù)做法。然而在 Angular 6 + 版本后,官方為 Injectable 裝飾器提供了 providedIn: "root" 的選項(xiàng),讓聲明的服務(wù)直接成為單例服務(wù),此后再不用通過“CoreModule”來提供服務(wù),但是我們的單例服務(wù)仍然可以放在 core目錄 中,通過 路徑別名 配置來直接訪問服務(wù),因?yàn)閷?shí)際上,單例服務(wù)只會(huì)乖乖在 core目錄中 ,不會(huì)再有其他東西來干擾。
只需引入一次的?:什么是項(xiàng)目中只需要引入一次的?舉個(gè)例子,全局錯(cuò)誤處理、根路由數(shù)據(jù)預(yù)加載、http請(qǐng)求攔截器等。這些都是通過一次配置就能一直用到老的東西,而且不可能會(huì)有其他兄弟來直接使用的東西,順理成章就需要?dú)w并到 core目錄 中,并且有的需要被“CoreModule”引用,有的需要被“AppModule”引用。
我列舉來幾個(gè)更加詳細(xì)的例子來說說這些類別:
應(yīng)用初始數(shù)據(jù)加載在開發(fā)單頁(yè)應(yīng)用特別是管理系統(tǒng)的時(shí)候,可能項(xiàng)目的構(gòu)成除了中心主系統(tǒng)還衍生了很多個(gè)子項(xiàng)目系統(tǒng),這種情況下登錄授權(quán)一般都是在主系統(tǒng)完成,然后前后端通過單點(diǎn)登錄確保子系統(tǒng)能使用。這時(shí)子系統(tǒng)一般都是一個(gè)新的項(xiàng)目,我們都知道 Angular 提供了強(qiáng)大的路由功能,可以通過路由守衛(wèi)來預(yù)加載系統(tǒng),然而我們需要的授權(quán)信息是相對(duì)整個(gè)應(yīng)用而不是某個(gè)路由而言的,那這個(gè)時(shí)候我們就需要一個(gè)根級(jí)別的數(shù)據(jù)預(yù)加載功能來完成授權(quán)等功能。
Angular 還是幫你開辟好了入口,這時(shí)我們只需要一個(gè)APP_INITIALIZER就可以完成預(yù)加載。前提是我們定義好了預(yù)加載的數(shù)據(jù)操作邏輯,舉個(gè)例子:
/** * app 初始化前身份驗(yàn)證操作 */ @Injectable({ providedIn: "root" }) export class AppInitAuthService { constructor( ..., private userInfoService: UserInfoService, ) { } /** 驗(yàn)證當(dāng)前token身份 */ tokenAuth(): Promise{ return new Promise((resolve,reject) => { return this.userInfoService.getUserInfoServer().subscribe(res => { if(res.reasonCode == "notLoggedIn"){ //未登錄 //可以進(jìn)行取消授權(quán)處理 ... }else{ //獲取了授權(quán)數(shù)據(jù),todo ... resolve(true) } }) }) } }
此處聲明了一個(gè)基本的用戶授權(quán)信息獲取服務(wù),接下來我們可以直接通過APP_INITIALIZER來完成數(shù)據(jù)預(yù)加載功能,只需要在 CoreModule 中聲明剛才提供的處理服務(wù),Angular 會(huì)自動(dòng)在根組件初始化前查詢并執(zhí)行 APP_INITIALIZER 所注入的所有服務(wù)函數(shù),由于我們提供的是一個(gè) Promise 對(duì)象,所以 Angular 會(huì)等待執(zhí)行結(jié)果:
@NgModule({ ... providers: [ ... { provide: APP_INITIALIZER, multi: true, useFactory: (appInit: AppInitAuthService) => { return () => appInit.tokenAuth() }, deps: [AppInitAuthService] } ] }) export class CoreModule { constructor( ... ) {} }
只要AppModule引用了CoreModule,項(xiàng)目會(huì)自動(dòng)完成預(yù)授權(quán)處理功能,完全無需其他組件摻入。
全局錯(cuò)誤處理有時(shí)候我們需要全局錯(cuò)誤處理機(jī)制。比如我們編譯更新了項(xiàng)目版本,多個(gè)某個(gè)模塊功能,但是用戶這邊并沒有去實(shí)時(shí)刷新,當(dāng)意外去到某個(gè)原本不存在的路由時(shí) Angular 會(huì)捕獲到找不到模塊的錯(cuò)誤,這是我們就可以提前在錯(cuò)誤處理中去對(duì)用戶進(jìn)行較友好的提示等等;又比如我們會(huì)想要去接入前端監(jiān)控平臺(tái)像 fundebug 等等,具體對(duì)實(shí)現(xiàn)方式也是一樣通過 Angular 提供的捕錯(cuò)功能來實(shí)現(xiàn)。
一個(gè)最簡(jiǎn)單的錯(cuò)誤處理服務(wù)如下:
import { ErrorHandler } from "@angular/core" export class HandleCommon extends ErrorHandler{ constructor(){ super() } handleError(error: Error){ //注意調(diào)基類處理函數(shù),不然會(huì)覆蓋默認(rèn)行為,比如控制臺(tái)不會(huì)看到報(bào)錯(cuò) super.handleError(error) if (/Loading chunk [d]+ failed/.test(error.message)) { //捕獲找不到模塊 (服務(wù)端目錄數(shù)據(jù)變動(dòng)) ... } //... 各種錯(cuò)誤處理 } }
然后我們直接在AppModule中聲明一個(gè) ErrorHandler 令牌對(duì)應(yīng)的服務(wù),就可以實(shí)現(xiàn)全局錯(cuò)誤監(jiān)聽處理:
import { NgModule, ErrorHandler } from "@angular/core" import { HandleCommon } from "../core" @NgModule({ ... providers: [ ... { provide: ErrorHandler, useFactory: () => { return new HandleCommon() } } ], bootstrap: [ AppComponent ] }) export class AppModule { }http請(qǐng)求攔截器
盡管 Angular 提供了十分漂亮的 HttpClient 給開發(fā)者舒服地進(jìn)行網(wǎng)絡(luò)請(qǐng)求操作,但是有很多針對(duì)網(wǎng)絡(luò)請(qǐng)求的需求需要我們自己去開發(fā),像 http 超時(shí)攔截、token 攔截、錯(cuò)誤處理攔截等等,這些也都屬于一次引用,全局使用的范疇。更漂亮的是 Angular 為我們提供了攔截器接口,我們只管開發(fā)攔截器邏輯功能,調(diào)用及使用全部控制權(quán)都在框架內(nèi)。由于攔截器涉及比較多東西,這里放一個(gè)最為簡(jiǎn)單的實(shí)現(xiàn)如下:
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http" import { Injectable } from "@angular/core" import { Observable } from "rxjs" import { tap } from "rxjs/operators" //攔截器 - 添加請(qǐng)求頭 @Injectable() export class TokenInterceptor implements HttpInterceptor { constructor() { } intercept(req: HttpRequest, next: HttpHandler): Observable > { //通過某些邏輯獲取 token let token = "xxxx" if (token) { token = `Bearer ${token}` req = req.clone({ setHeaders: { Authorization: token } }) } return next.handle(req) } }
只需要在 CoreModule 中通過 HTTP_INTERCEPTORS 令牌來聲明我們寫好的攔截器,框架會(huì)在正確的時(shí)機(jī)自動(dòng)處理和調(diào)用攔截器邏輯:
@NgModule({ providers: [ ..., { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, //必須設(shè)置,攔截器是個(gè)數(shù)組集合而不僅僅只有一個(gè) multi: true } ] }) export class CoreModule { constructor() {} }一些單例服務(wù)等等
應(yīng)用中或多或少有一些需要在全局流通的數(shù)據(jù),比如全局的用戶信息管理:
@Injectable({ providedIn: "root" }) export class UserInfoService { //用戶數(shù)據(jù) 全局共享 數(shù)據(jù)流 userInfo$: BehaviorSubject= new BehaviorSubject (null) constructor() { } /** * 獲取用戶數(shù)據(jù) */ getUserInfoServer(): Observable { ... } /** * 退出登錄 */ getUserLogoutServer(): Observable { ... } }
作為頻繁被存取的介質(zhì),單例模式自然而然是它的特點(diǎn),所以最好也一起歸并到所謂的 core目錄 中。
因人而異前面列舉了一些常用的類別來說明 core目錄 以及 “CoreModule” 存在的意義。除了一些需要“CoreModule”來作為橋梁的例子,貌似 core目錄 并不是必須要存放某些東西的,比如全局的單例對(duì)象就完全可以多帶帶使用其他的文件夾來存放維護(hù)。是對(duì)的,沒有一個(gè)統(tǒng)一的標(biāo)準(zhǔn)來約束我們到底是要去如何組織代碼目錄結(jié)構(gòu),所有項(xiàng)目都是因人而異,自己覺得舒服的、可維護(hù)的才最重要。
本記錄只是為了更加貼近官方最佳實(shí)踐而如此組織,純粹作為一個(gè)記錄以及給大家的一個(gè)參考。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102477.html
摘要:二來,給大家新開坑的項(xiàng)目一個(gè)參考。因此,本系列以主要以官方文檔為基礎(chǔ),將盡可能多的特性融入本項(xiàng)目,并標(biāo)注官網(wǎng)原文出處,有興趣的小伙伴可點(diǎn)擊深入了解。可以通過一些特殊協(xié)議例如將消息作為統(tǒng)一消息服務(wù)導(dǎo)出。下載完成后自行修改和。 開坑前言 我給這個(gè)專欄的名氣取名叫做小項(xiàng)目,聽名字就知道,這個(gè)專題最終的目的是帶領(lǐng)大家完成一個(gè)項(xiàng)目。為什么要開這么大一個(gè)坑呢,一來,雖然網(wǎng)上講IT知識(shí)點(diǎn)的書籍鋪天蓋...
摘要:開始項(xiàng)目前,你需要先安裝和,然后執(zhí)行安裝。一用命令行新建一個(gè)項(xiàng)目執(zhí)行上面的命令就會(huì)自動(dòng)新建一個(gè)項(xiàng)目,并啟動(dòng)了項(xiàng)目。 作者:心葉時(shí)間:2018-04-22 09:13 Angular CLI是一個(gè)命令行界面工具,它可以創(chuàng)建項(xiàng)目、添加文件以及執(zhí)行一大堆開發(fā)任務(wù),比如測(cè)試、打包和發(fā)布,這里的快速開始就是基于這個(gè)命令。 開始項(xiàng)目前,你需要先安裝node和npm,然后執(zhí)行npm install ...
閱讀 2335·2021-11-15 11:38
閱讀 3544·2021-09-22 15:16
閱讀 1187·2021-09-10 11:11
閱讀 3156·2021-09-10 10:51
閱讀 2921·2019-08-30 15:56
閱讀 2774·2019-08-30 15:44
閱讀 3185·2019-08-28 18:28
閱讀 3525·2019-08-26 13:36