英文:
Angular directive this and closure issue
问题
问题是在moveImage
函数内部,this
的上下文不正确,导致它根本不起作用。您犯了一个常见的错误,可以通过以下方式来修复它:
private moveImage = (e: MouseEvent): void => {
let pos: { x: number; y: number }, x: number, y: number;
e.preventDefault();
/* 这里执行一些代码,也使用了 this.getPos(e) */
}
通过使用箭头函数来定义moveImage
,您可以确保它在执行时保持正确的上下文,而不会丢失this
的引用。这应该解决您遇到的问题。
英文:
I have such directive:
@Directive({
selector: '[imgTest]',
})
export class ImgTest implements AfterViewInit, OnDestroy {
private originalImage: HTMLImageElement;
private secondImage: HTMLDivElement;
constructor(private elementRef: ElementRef, public sanitizer: DomSanitizer) {}
@HostListener('load')
public onLoad(): void {
this.process();
}
public ngAfterViewInit(): void {
this.originalImage = this.elementRef.nativeElement;
}
public ngOnDestroy(): void {
this.removeEventListeners();
}
private addEventListeners(): void {
this.originalImage.addEventListener('mousemove', this.moveImage);
this.secondImage.addEventListener('mousemove', this.moveImage);
}
private removeEventListeners(): void {
this.originalImage.removeEventListener('mousemove', this.moveImage);
this.secondImage.removeEventListener('mousemove', this.moveImage);
}
private process(): void {
if (!this.originalImage) {
return;
}
/* some magic */
this.addEventListeners();
}
private moveImage(e: MouseEvent): void {
let pos: { x: number; y: number }, x: number, y: number;
e.preventDefault();
/* some magic that is using also this.getPos(e) */
}
private getPos(e: MouseEvent): { x: number; y: number } {
/* some magic */
return { x: x, y: y };
}
}
and the issue is that inside moveImage
this is wrong and it's just not working at all.
what I've done wrong?
答案1
得分: 1
因为在addEventListener
内部,this
关键字不指向该类。您应该将代码修改为以下方式:
constructor(private elementRef: ElementRef, public sanitizer: DomSanitizer) {
this.moveImage = this.moveImage.bind(this);
}
绑定了moveImage
之后,它将按预期工作。
英文:
It's because inside the addEventListener
, this
keyword doesn't refer to the class. You should modify your code to the following:
constructor(private elementRef: ElementRef, public sanitizer: DomSanitizer) {
this.moveImage = this.moveImage.bind(this);
}
After binding moveImage
, it will work as expected
答案2
得分: 1
当您像这样添加监听器时
this.originalImage.addEventListener('mousemove', this.moveImage);
您基本上破坏了 "this" 引用。
为了保留正确的 "this" 引用,您可以以另一种方式添加监听器 - 您应该创建另一个回调函数,该回调函数会在正确的上下文中调用方法
this.originalImage.addEventListener('mousemove', (e) => this.moveImage(e));
// 或者
this.originalImage.addEventListener('mousemove', this.moveImage.bind(this));
// 或者
boundMoveImage = this.moveImage.bind(this) // 在类的某处内部
...
...addEventListener('mousemove', this.boundMoveImage); // 这样您可以在删除回调时删除事件监听器
英文:
when you are adding a listener like this
this.originalImage.addEventListener('mousemove', this.moveImage);
you are basically breaking "this" reference.
to preserve correct "this" it you could add a listener in an other way - you should create another callback which would call the method in the correct context
this.originalImage.addEventListener('mousemove', (e) => this.moveImage(e));
// or
this.originalImage.addEventListener('mousemove', this.moveImage.bind(this));
// or
boundMoveImage = this.moveImage.bind(this) // somewhere inside of a class
...
...addEventListener('mousemove', this.boundMoveImage); // this way you could removeEventListeners in remove callbacks
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论