我正在编写一个包含2个@Input()
变量的指令,并从使用该指令的组件中获取值。
一切都好。唯一的问题是,当构造函数中有Observable.subscribe
时,@Input
值在构造函数中可用而没有Observable.subscribe
@Input()
变量值是undefined
我知道获取指令的@Input()
变量的更好方法是在ngOnInit
或ngOnChange
等生命周期钩子中访问它们,但我的问题是:为什么在某些情况下这是可用的,而在指令的其他情况下则不可用。
<div authorizedme
[permission]="'manager'"
[auth]="department"
class="col-2 data-object-link">your salary is $90,000,0000
如果在subscribe
代码下面的指令构造函数中,那么权限和auth可用,如果它被注释掉,那么两个@Input()
变量都是undefined
。
this.userService.getUser().subscribe((user) => {
this.user = user;
if (this.authorized()) {
this.elementRef.nativeElement.style.display = 'block';
}
});
以下是整个指令代码
@Directive({
selector: '[authorizedme]'
})
export class AuthorizedDirective implements OnInit {
@Input() permission: string;
@Input() auth: string;
private user: any;
constructor(private elementRef: ElementRef, private currentUserService: userService) {
this.elementRef.nativeElement.style.display = 'none';
this.currentUser = this.userService.userAuthorizations;
/*this.currentUserService.getUser().subscribe((user) => {
this.user = user;
if (this.authorized()) {
this.elementRef.nativeElement.style.display = 'block';
}
});*/
}
public authorized() {
return this.user || authorize;
}
}
这是生命周期钩子和异步处理的经典案例!
一步一步走:
将这一切放在一起意味着Angular用它的构造函数实例化你的指令AuthorizedDirective。在该函数的上下文中,auth和currentUser都是未定义的,因为您还没有为它们设置值。然后,您订阅将在服务中发生的更改,这些更改基本上是在我们处理可观察对象之后注册的函数。
因为它发生了可观察性,直到他们为Angular所在的区域打勾才进行处理。
在ngOnInit中设置权限/身份验证的原因是因为在Angular实例化了您的对象之后,它会解析它以查看您是否有要使用的任何输入或输出值。如果这样做,它会查找在元素上设置的相应内容,并在调用ngOnInit之前设置它们,这是在区域标记发生之前。
所以这就是你在subscribe和ngOnInit中获得值的原因,但你没有构造函数本身的值。
不要试图访问@Input()
中的constructor
s,在ngOnInit
生命周期钩子中进行。构造函数几乎与Angular应用程序生命周期无关。
在初始化指令的数据绑定属性后,实现此接口以执行自定义初始化逻辑。在第一次检查指令的数据绑定属性之后,以及在检查其任何子项之前,立即调用ngOnInit。实例化指令时仅调用一次。
此外,构造函数不是Angular特性,而是TypeScript特性。直接引用Günter对上述相关答案的评论:
Contstructors与Angular2无关,它们是TypeScript特性。在进行一些初始化或某些事件发生以允许组件在某些情况下起作用并使其有机会在适当的时间执行某些任务时,Angular会调用生命周期钩子。
因此,可以预期,构造函数中尚未提供数据绑定属性。
然后有角度的文档说,每当输入绑定属性发生更改时,您想要检测到更改,您应该使用生命周期挂钩。构造函数是生命周期的早期阶段,你能尝试在ngOnCanges中做什么,它可能会帮助你解决问题