這篇文章我們分析TypeDoc中的Component裝飾器。
讓我們退後一步,先了解什麼是 TypeScript 中的裝飾器。
A Decorator 是一種特殊類型的聲明,可以附加到類別聲明、方法、存取器、屬性或參數。裝飾器使用@表達式的形式,其中表達式必須計算為一個函數,該函數將在運行時調用,並包含有關裝飾聲明的資訊。 - 來源。
例如,給定裝飾器@sealed,我們可以將密封函數編寫如下:
function sealed(target) { // do something with 'target' ... }
讓我們從 TypeScript 文件中挑選一個簡單易懂的範例來了解如何使用類別裝飾器。
@sealed class BugReport { type = "report"; title: string; constructor(t: string) { this.title = t; } }
這裡@sealed是一個類別裝飾器,應用在類別聲明之上。這個@sealed是一個在運行時應用的裝飾器。
如果你想防止對BugReport類別進行任何修改,你可以定義密封函數如下:
function sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype); }
當執行@sealed 時,它將密封構造函數及其原型,因此將防止在運行時通過訪問BugReport.prototype 或通過在BugReport 本身上定義屬性來向此類添加或刪除任何進一步的功能-來源
有了這些知識,我們現在準備好了解 TypeDoc 程式碼庫中的 @Component 裝飾器。
@Component 裝飾器是從 lib/utils/components.ts 導入的
這是一個裝飾器工廠,它傳回一個在運行時執行的箭頭函數。您可以在 TS 文件中閱讀有關裝飾器工廠的更多資訊。
export function Component(options: ComponentOptions) { // _context is ClassDecoratorContext, but that then requires a public constructor // which Application does not have. return (target: Function, _context: unknown) => { const proto = target.prototype; if (!(proto instanceof AbstractComponent)) { throw new Error( "The `Component` decorator can only be used with a subclass of `AbstractComponent`.", ); } if (options.childClass) { if (!(proto instanceof ChildableComponent)) { throw new Error( "The `Component` decorator accepts the parameter `childClass` only when used with a subclass of `ChildableComponent`.", ); } childMappings.push({ host: proto, child: options.childClass, }); } const name = options.name; if (name) { proto.componentName = name; } // If not marked internal, and if we are a subclass of another component T's declared // childClass, then register ourselves as a _defaultComponents of T. const internal = !!options.internal; if (name && !internal) { for (const childMapping of childMappings) { if (!(proto instanceof childMapping.child)) { continue; } const host = childMapping.host; host["_defaultComponents"] = host["_defaultComponents"] || {}; host["_defaultComponents"][name] = target as any; break; } } }; }
這個組件裝飾器中發生了很多事情,我們不要試圖理解所有內容,而是選擇我們可以推斷出的簡單內容。
此檢查用於在實例不受支援的情況下引發錯誤。
2. proto.componentName
proto.componentName 根據傳遞給裝飾器的名稱進行更新。在本例中,名稱設定為“application”。
3.子映射
// If not marked internal, and if we are a subclass of // another component T's declared // childClass, then register ourselves as a _defaultComponents of T. const internal = !!options.internal; if (name && !internal) { for (const childMapping of childMappings) { if (!(proto instanceof childMapping.child)) { continue; } const host = childMapping.host; host["_defaultComponents"] = host["_defaultComponents"] || {}; host["_defaultComponents"][name] = target as any; break; } }
childMapping.host 做了一些更新
在 Think Throo,我們的使命是教授開源專案中使用的高階程式碼庫架構概念。
透過在 Next.js/React 中練習高階架構概念,提升您的程式設計技能,學習最佳實踐並建立生產級專案。
我們是開源的 — https://github.com/thinkthroo/thinkthroo (請給我們一顆星!)
我們也提供網路開發與技術寫作服務。請透過 [email protected] 與我們聯絡以了解更多資訊!
https://github.com/TypeStrong/typedoc/blob/master/src/lib/application.ts#L100
https://www.typescriptlang.org/docs/handbook/decorators.html
https://github.com/TypeStrong/typedoc/blob/master/src/lib/utils/component.ts#L39
https://www.typescriptlang.org/docs/handbook/decorators.html#decorator-factories
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3