이 글에서는 TypeDoc의 Component 데코레이터를 분석합니다.
한발 물러서서 먼저 TypeScript의 데코레이터가 무엇인지 이해해 보겠습니다.
데코레이터는 클래스 선언, 메서드, 접근자, 속성 또는 매개 변수에 연결할 수 있는 특별한 종류의 선언입니다. 데코레이터는 @expression 형식을 사용합니다. 여기서 표현식은 데코레이팅된 선언에 대한 정보와 함께 런타임에 호출될 함수로 평가되어야 합니다. - 원천.
예를 들어 데코레이터 @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/comComponents.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.comComponentName
proto.comComponentName은 데코레이터에 전달된 이름을 기반으로 업데이트됩니다. 이 경우 이름은 "application"으로 설정됩니다.
3. child매핑
// 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에서 고급 아키텍처 개념을 연습하여 코딩 기술을 10배 높이고, 모범 사례를 배우고, 프로덕션급 프로젝트를 구축하세요.
저희는 오픈 소스입니다 — 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/comComponent.ts#L39
https://www.typescriptlang.org/docs/handbook/ decorators.html# decorator-factories
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3