gpt4 book ai didi

javascript - Angular 2 自己的类装饰器来访问依赖注入(inject)服务

转载 作者:搜寻专家 更新时间:2023-10-30 21:52:16 25 4
gpt4 key购买 nike

我想创建一个类装饰器 TopicClass,它向装饰组件添加一个属性和一个函数。该函数必须访问注入(inject)的服务。 我该怎么做?

下面是失败的尝试:


@Component({
selector: 'home',
styleUrls: ['./home.component.css'],
templateUrl: './home.component.html'
})
@TopicClass('home')
export class HomeComponent {
constructor(private topicService: TopicService) { }
}

我无法通过插入的函数 ngAfterViewInit 访问注入(inject)的服务。


export function TopicClass(title: string) {
return function (target: Function) {
const original = target;

function construct(constructor, args) {
const c: any = function () {
return constructor.apply(this, args);
}
c.prototype = constructor.prototype;

const newInstance = new c();
newInstance['topic'] = new Topic(title, '');

newInstance['ngAfterViewInit'] = () => {
newInstance['topicService'].setTopic(newInstance['topic']);
}
return newInstance;
}

const ctor: any = (...args) => {
console.log("Service: " + original.prototype.topicService);
return construct(original, args);
};

ctor.prototype = original.prototype;
return ctor;
}
}

问题是 newInstance['topicService'] 未定义。

我已经建立了一个简单的 Angular 项目用于测试: https://github.com/ptea/angular-class-decorator-test

https://github.com/ptea/angular-class-decorator-test/blob/master/src/app/services/topic.service.ts

我还尝试使用一个简单的 TypeScript 程序重现该问题,该程序按预期工作:


newInstance['printStreet'] = () => {
console.log(`printFirstnameStreet: ${newInstance['firstname']}, ${newInstance['street']}`);
}

https://github.com/ptea/angular-class-decorator-test/blob/master/dashboard.ts

对这个问题有什么想法/解决方案吗?

最佳答案

TopicService 未定义的原因是因为它从未被注入(inject)到组件中。使用您当前的装饰器,它将 HomeComponent 的构造函数重新定义为没有参数的构造函数。这搞乱了 Angular 的 DI,因此 TopicService 不会在组件实例化时注入(inject)。

我能想到的最好的方法是不修改 HomeComponent 的构造函数,而是使用 ngOnInit 方法。 ngOnInit 方法是一个理想的候选方法,因为它在每个组件的生命周期中被调用一次,并且它具有固定数量的参数 0,这使得它很容易包装在另一个函数中。您可以使用 ngAfterViewInit 函数类似地执行此操作,以便在需要时使用该服务。

您可以通过以下方式修改 TopicClassDecorator 以获得您想要的结果:

export function TopicClass(title: string) {
return function (target: Function) {

let targetNgOnInit = target.prototype.ngOnInit;
target.prototype.ngOnInit = function (){
this.topic = new Topic(title, 'subTitle');

if(targetNgOnInit){
targetNgOnInit.apply(target);
}
}

let targetNgAfterViewInit = target.prototype.ngAfterViewInit;
target.prototype.ngAfterViewInit = function (){
this.topicService.setTopic(this.topic);

if(targetNgAfterViewInit){
targetNgAfterViewInit.apply(target);
}
}

return target;
}
}

Demo Plunkr一切都协同工作。

关于javascript - Angular 2 自己的类装饰器来访问依赖注入(inject)服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41490450/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com