Angular @Component 装饰器实现解析
Angular 的 @Component
装饰器是 Angular 框架中用于定义组件的重要装饰器。以下是其完整实现和关键部分的解析:
@Component 装饰器接口定义
typescript
csharp
interface ComponentDecorator {
(obj: Component): TypeDecorator;
new (obj: Component): Component;
}
完整的 @Component 装饰器实现
typescript
typescript
import { TypeDecorator, makeDecorator } from '@angular/core';
import { ViewEncapsulation } from './view_encapsulation';
export interface Component {
// 组件选择器 (CSS 选择器)
selector?: string;
// 组件模板 URL
templateUrl?: string;
// 内联模板
template?: string;
// 样式 URL
styleUrls?: string[];
// 内联样式
styles?: string[];
// 视图封装模式
encapsulation?: ViewEncapsulation;
// 组件使用的指令
directives?: Array<Type | any[]>;
// 组件使用的管道
pipes?: Array<Type | any[]>;
// 变更检测策略
changeDetection?: ChangeDetectionStrategy;
// 组件动画
animations?: any[];
// 组件注入器
providers?: Provider[];
// 组件导出为
exportAs?: string;
// 是否保留空白
preserveWhitespaces?: boolean;
// 组件生命周期钩子
lifecycle?: LifecycleHooks;
// 组件初始化逻辑
init?: () => void;
// 组件销毁逻辑
destroy?: () => void;
}
export const Component: ComponentDecorator = makeDecorator('Component', (c: Component = {}) => ({
selector: c.selector,
template: c.template,
templateUrl: c.templateUrl,
styles: c.styles,
styleUrls: c.styleUrls,
directives: c.directives,
pipes: c.pipes,
encapsulation: c.encapsulation,
changeDetection: c.changeDetection,
animations: c.animations,
providers: c.providers,
exportAs: c.exportAs,
preserveWhitespaces: c.preserveWhitespaces
}));
使用示例
typescript
php
import { Component } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
styleUrls: ['./example.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ExampleComponent {
// 组件逻辑
}
核心实现解析
-
makeDecorator
是 Angular 内部用于创建装饰器的工厂函数 -
ComponentDecorator
接口定义了装饰器的两种使用方式:- 作为函数调用
@Component({...})
- 作为构造函数
new Component({...})
- 作为函数调用
-
主要配置选项包括:
- 模板相关:
template
,templateUrl
,styles
,styleUrls
- 元数据:
selector
,exportAs
- 依赖注入:
providers
- 变更检测:
changeDetection
- 视图封装:
encapsulation
- 模板相关:
底层实现原理
在 Angular 内部,@Component
装饰器实际上是一个元数据注解,它会在编译时被 Angular 的编译器收集并处理,最终生成组件工厂函数和相关的视图定义。
注意:以上代码是简化后的表示,实际的 Angular 源码实现更为复杂,涉及更多的内部处理逻辑和与编译器的集成。
Angular makeDecorator
实现解析
makeDecorator
是 Angular 内部用来创建装饰器工厂的核心函数。以下是其完整实现代码和解析:
完整实现代码
typescript
typescript
export function makeDecorator<T>(
name: string,
props?: (...args: any[]) => any,
parentClass?: any,
chainFn?: (fn: Function) => void
): (...args: any[]) => (cls: any) => any {
const metaCtor = makeMetadataCtor(props);
function DecoratorFactory(...args: any[]): (cls: any) => any {
if (this instanceof DecoratorFactory) {
metaCtor.apply(this, args);
return this;
}
const annotationInstance = new (DecoratorFactory as any)(...args);
return function TypeDecorator(cls: any) {
if (chainFn) chainFn(annotationInstance);
// 使用 Reflect 保存元数据
const annotations = Reflect.getOwnMetadata('annotations', cls) || [];
annotations.push(annotationInstance);
Reflect.defineMetadata('annotations', annotations, cls);
return cls;
};
}
if (parentClass) {
DecoratorFactory.prototype = Object.create(parentClass.prototype);
}
DecoratorFactory.prototype.ngMetadataName = name;
(DecoratorFactory as any).annotationCls = DecoratorFactory;
return DecoratorFactory;
}
function makeMetadataCtor(props?: (...args: any[]) => any): any {
return function MetadataCtor(...args: any[]) {
if (props) {
const values = props(...args);
for (const propName in values) {
this[propName] = values[propName];
}
}
};
}
关键部分解析
-
函数签名:
typescript
typescriptfunction makeDecorator<T>( name: string, // 装饰器名称(如'Component') props?: (...args: any[]) => any, // 属性处理函数 parentClass?: any, // 父类 chainFn?: (fn: Function) => void // 链式处理函数 ): (...args: any[]) => (cls: any) => any
-
核心流程:
- 创建一个元数据构造函数(
metaCtor
) - 返回一个装饰器工厂函数(
DecoratorFactory
) - 当装饰器被调用时,会创建注解实例并附加到类的元数据中
- 创建一个元数据构造函数(
-
元数据处理:
- 使用
Reflect.defineMetadata
API 存储装饰器产生的元数据 - 元数据存储在
annotations
键下,是一个数组
- 使用
-
支持两种使用方式:
typescript
java// 作为装饰器工厂 @DecoratorFactory(options) // 作为构造函数 new DecoratorFactory(options)
使用示例
typescript
kotlin
// 创建一个自定义装饰器
const MyDecorator = makeDecorator('MyDecorator', (data: any) => ({
config: data.config || 'default',
value: data.value || 0
}));
// 使用方式1: 作为装饰器
@MyDecorator({config: 'special', value: 42})
class MyClass {}
// 使用方式2: 作为注解
const annotation = new MyDecorator({config: 'another'});
与@Component的关系
Angular 的 @Component
装饰器就是通过 makeDecorator
创建的:
typescript
javascript
export const Component: ComponentDecorator = makeDecorator('Component', (c: Component = {}) => ({
selector: c.selector,
template: c.template,
templateUrl: c.templateUrl,
// ...其他属性
}));
这个实现展示了 Angular 装饰器系统的核心机制,使得各种装饰器(@Component
, @Directive
, @Injectable
等)能够共享相同的基础设施。