기본 클래스 장식기로 구성 요소 장식기 확장
모든 구성요소에 대해 반복하는 몇 가지 구성요소 장식자 선언이 있습니다. 예:
@Component({
moduleId: module.id,
directives: [BootstrapInputDirective]
})
이러한 선언을 모든 구성 요소에 적용하려면 어떻게 해야 합니까?이 데코레이터로 기본 클래스를 만들고 다른 클래스를 확장하려고 했는데 파생 클래스에는 기본 클래스 장식이 적용되지 않는 것 같습니다.
@Component
장식가입니다.즉, 리플렉트 메타데이터 라이브러리를 활용하여 일부 메타데이터 데이터를 추가하여 적용되는 클래스를 처리합니다.Angular2는 상위 클래스에서 메타데이터를 찾지 않습니다.이러한 이유로 부모 클래스에서는 장식자를 사용할 수 없습니다.
에 대해서는BootstrapInputDirective
지시, 당신은 그것을 플랫폼 1로 정의할 수 있습니다.이 방법을 사용하면 매번 파일에 포함할 필요가 없습니다.directives
사용자 구성 요소의 속성입니다.
다음은 샘플입니다.
(...)
import {PLATFORM_DIRECTIVES} from 'angular2/core';
bootstrap(AppComponent, [
provide(PLATFORM_DIRECTIVES, {useValue: [BootstrapInputDirective], multi:true})
]);
편집
예, 당신은 이것을 구현하기 위해 당신만의 장식가를 만들 수 있습니다.다음은 샘플입니다.
export function CustomComponent(annotation: any) {
return function (target: Function) {
var parentTarget = annotation.parent;
delete annotation.parent;
var parentAnnotations = Reflect.getMetadata('annotations', parentTarget);
var parentAnnotation = parentAnnotations[0];
Object.keys(parentAnnotation).forEach(key => {
if (isPresent(parentAnnotation[key])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
그CustomComponent
데코레이터는 다음과 같이 사용됩니다.
@Component({
template: `
<div>Test</div>
`
})
export class AbstractComponent {
}
@CustomComponent({
selector: 'sub',
parent: AbstractComponent
})
export class SubComponent extends AbstractComponent {
}
장식자 내에서 이 부모 클래스를 찾을 수 있기 때문에 부모 클래스를 장식자의 입력으로 제공해야 합니다.이 클래스의 프로토타입만 적용되고 메타데이터는 반사 메타데이터에 의해 관련 프로토타입에 적용되지 않습니다.
편집2
Nitzam의 답변 덕분에 개선 사항이 있습니다.
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])) {
annotation[key] = parentAnnotation[key];
}
});
var metadata = new ComponentMetadata(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
의 필요성은 없습니다.parent
사용자 지정 장식기의 상위 클래스를 참조하는 속성입니다.
다음 플런크r을 참조하십시오. https://plnkr.co/edit/ks1iK41sIBFlYDb4aTHG?p=preview
다음 질문을 참조하십시오.
현재 기능을 찾고 있는 경우:
function isPresent(obj: any): boolean { return obj !== undefined && obj !== null; }
Angular의 최신 릴리스 이후, ComponentMetadata 클래스는 여기에 있는 소수의 구성원들이 지적한 것처럼 사용할 수 없습니다.
사용자 지정 구성 요소를 구현하여 작동시키는 방법은 다음과 같습니다.
export function CustomComponent(annotation: any) {
return function (target: Function) {
let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
let parentAnnotations = Reflect.getOwnMetadata('annotations', parentTarget);
let parentAnnotation = parentAnnotations[0];
Object.keys(annotation).forEach(key => {
parentAnnotation[key] = annotation[key];
});
};
}
도움이 되길 바랍니다!
EDIT: 이전 코드 청크는 작동하더라도 확장 클래스의 원래 메타데이터를 재정의합니다.기본 클래스를 수정하지 않고 여러 상속 및 재정의를 가질 수 있는 향상된 버전의 아래를 확인하십시오.
export function ExtendComponent(annotation: any) {
return function (target: Function) {
let currentTarget = target.prototype.constructor;
let parentTarget = Object.getPrototypeOf(target.prototype).constructor;
let parentAnnotations = Reflect.getOwnMetadata('annotations', parentTarget);
Reflect.defineMetadata('annotations', [Object.create(parentAnnotations[0])], currentTarget);
let currentAnnotations = Reflect.getOwnMetadata('annotations', currentTarget);
Object.keys(annotation).forEach(key => {
currentAnnotations[0][key] = annotation[key];
});
};
}
업데이트된 해결책을 찾고 있는 사람이 있다면 티에리 템플러의 대답은 거의 완벽합니다.그것을 제외하고는ComponentMetadata
더 이상 사용되지 않습니다.용사를 합니다.Component
대신 나를 위해 일했습니다.
커스텀 풀커텀데이터레코스.CustomDecorator.ts
파일은 다음과 같습니다.
import 'zone.js';
import 'reflect-metadata';
import { Component } from '@angular/core';
import { isPresent } from "@angular/platform-browser/src/facade/lang";
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])) {
// verify is annotation typeof function
if(typeof annotation[key] === 'function'){
annotation[key] = annotation[key].call(this, parentAnnotation[key]);
}else if(
// force override in annotation base
!isPresent(annotation[key])
){
annotation[key] = parentAnnotation[key];
}
}
});
var metadata = new Component(annotation);
Reflect.defineMetadata('annotations', [ metadata ], target);
}
}
다음 새 인 그런다새구요가로 가져옵니다.sub-component.component.ts
합니다.@CustomComponent
에 @Component
다음과 같이:
import { CustomComponent } from './CustomDecorator';
import { AbstractComponent } from 'path/to/file';
...
@CustomComponent({
selector: 'subcomponent'
})
export class SubComponent extends AbstractComponent {
constructor() {
super();
}
// Add new logic here!
}
Tierry Templier의 솔루션은 Angular 9+ check (Ivy, AOT) https://github.com/angular/angular/issues/31495 에서 제대로 작동하지 않을 것입니다.
다음과 같은 부트스트랩 기능으로 글로벌 서비스를 제공할 수 있습니다.
bootstrap(AppComponent, [HTTP_PROVIDERS, provide(SharedService, {useValue: sharedService})]);
여기서 sharedService는 가져온 서비스입니다.
언급URL : https://stackoverflow.com/questions/36837421/extending-component-decorator-with-base-class-decorator
'programing' 카테고리의 다른 글
필드 이름에서 점을 사용하는 방법은 무엇입니까? (0) | 2023.07.06 |
---|---|
Python Pandas:에서 CSV 파일의 첫 번째 n 행만 읽는 방법은 무엇입니까? (0) | 2023.07.06 |
NULL 값이 있는 열만 선택 (0) | 2023.07.01 |
react import 문에서 @ 기호는 무엇을 의미합니까? (0) | 2023.07.01 |
Mac OS X v10.9(Mavericks)의 터미널에서 apt-get 기능이 작동하지 않는 이유는 무엇입니까? (0) | 2023.07.01 |