我正在使用带有TypeScript的Angular2创建Web应用程序。当我创建一些CustomElements(它的意思是组件和指令,验证器)时,我发现我为每个组件编写了directives: [...]
代码,以便导入CustomElements,如下面的代码。
// my_comopnent_1.comopnent.ts
@Component({
selector: 'my-component-1',
directives: [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2,
...
],
})
// my_comopnent_2.comopnent.ts
@Component({
selector: 'my-component-2',
directives: [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2,
...
],
})
// my_comopnent_3.comopnent.ts
@Component({
selector: 'my-component-3',
directives: [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2,
...
],
})
是否存在如何导入一些CustomComopnents而不重复编写directives: [...]
,如事件冒泡或原型链?
我的理想是,当我将代码编写到父组件时,其子组件将它们包含在父组件的导入的CustomElements中。
// parent.component.ts
@Component({
selector: 'parent',
directives: [MyDirective1, ...],
})
// child.component.ts
@Component({
selector: 'child',
template: `
// It's possible to use MyDirective because of importing by ParentComponent.
<div my-directive></div>
`,
})
答案 0 :(得分:0)
您可以通过这种方式将它们定义为平台指令:
export const GENERAL_DIRECTIVES: any[] = [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2,
(...)
];
bootstrap(App, [
provide(PLATFORM_DIRECTIVES, {useValue: [GENERAL_DIRECTIVES], multi: true})
]);
这样您每次都不需要导入它们。
有关详细信息,请参阅此问题:
这种方法的主要缺点是它们对应用程序中的所有组件都是全局的。另一种方法包括创建一个自定义装饰器,扩展组件元数据(directives
属性)以添加这些组件/指令。通过这种方式,您可以精确控制自动指定这些指令的位置。
这种机制可以依赖继承,即abtract root组件。
以下是一个示例:
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = Object.getPrototypeOf(target.prototype).constructor;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
if (key === 'directives') {
// merge directives attributes
let parentDirectives = parentAnnotation[key] || [];
let currentDirectives = annotation[key] || [];
currentDirectives.concat(parentDirectives);
} else {
annotation[key] = parentAnnotation[key];
}
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
并使用它:
@Component({
directives: [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2,
(...)
]
})
export class AbstractComponent {
}
@CustomComponent({
selector: 'sub',
template: `
(...)
`
})
export class SubComponent extends AbstractComponent {
}
@Component({
selector: 'app',
template: `
<sub></sub>
`,
directives [ SubComponent ]
})
export class App {
}
有关详细信息,请参阅此问题:
答案 1 :(得分:0)
您可以全局提供指令和代码,例如
bootstrap(AppComponent, [
provide(PLATFORM_DIRECTIVES,
{useValue: [
ROUTER_DIRECTIVES,
MyDirective1,
MyDirective2,
MyValidator1,
MyValidator2
], multi: true}),
provide(PLATFORM_PIPES,
{useValue: [RainbowizePipe], multi:true})
]);
您传递的指令和管道数组由Angulars DI自动展平,这允许传递任意嵌套数组。
例如,将模块的指令打包到数组中,然后最终将包含所有模块的数组的数组传递给provide()
。