今天,我尝试制作自己的注释,以便在Angular2项目中使用它。 此注释必须在特定组件上添加body类。
所以,我搜索了Angular源代码,但是很难看出注释的创建位置和方式。
目前,我已经尝试过这个:
export function BodyClass(classes: any): ClassDecorator{
classes = classes || {};
if(typeof classes === 'string'){
classes = {classes};
}
return function changeBodyClass(){
console.log('ici');
}
}
我的组件:
import {Component} from "angular2/core";
import {RouterOutlet} from "angular2/router";
import {BodyClass} from "../core/annotations/body_class";
@Component({
selector: 'my-component',
template: `
<router-outlet></router-outlet>
`,
})
@BodyClass('test')
export class MyComponent{
}
我的控制台登录注释被正确触发了,但是我想使用angular2/src/platform/dom/dom_adapter
中的“DOM”类添加我的类,但是在控制台登录时未定义DOM(不需要实例化)。
但是,DOM类在我的组件中直接运行良好。 我在ngOnInit函数中添加类,并在ngOnDestroy上删除它们。
但是,我想在许多组件上使用这种行为,我认为新的注释是最好的方法。
也许你对此有更好的想法?或者在注释中使用DOM类?
谢谢!
答案 0 :(得分:0)
由于您希望在组件实例级别而不是在组件类1中工作,因此不那么明显。所以你需要包装相应的构造函数。
export function MyComponentDecorator(value: string) {
return function (target: Function) {
var original = target;
function construct(constructor, args) {
var c : any = function () {
// Call the target constructor
var ret = constructor.apply(this, args);
// Add your additional processing
return ret;
}
c.prototype = constructor.prototype;
return new c();
}
// The new constructor
// Don't forget to add a name at this function
// since Angular requires it for the template compilation
var f : any = function WrappedComponent(...args) {
return construct(original, args);
}
f.prototype = original.prototype;
return f;
}
}
此时,您包装组件实例但丢失了组件元数据。你需要手工复制它们:
f.prototype = original.prototype;
var annotations = Reflect.getMetadata('annotations', original));
Reflect.defineMetadata('annotations', annotations, f);
var properties = Reflect.getMetadata('propMetadata', original));
Reflect.defineMetadata('propMetadata', properties, f);
return f;
要使用此装饰器,只需在@Component
之前或之后添加它:
@MyComponentDecorator()
@Component({
selector: 'sub',
template: `
<div (click)="showMessage()">Test</div>
`
})
export class SubComponent {
(...)
}
您可以注意到,此装饰器仅复制组件级别的元数据,而不复制其他类型的元数据(使用@Input
)...
请参阅此plunkr:https://plnkr.co/edit/PrAvliIpWTNFAtH33bHA?p=preview。