Javascript 的范围 "this" 在 Typescript 的 class 中
Javascript's scope "this" in Typescript's class
我正在尝试在切换视频时更改视频的自定义图标(Play/Pause)。
ngAfterViewInit() {
const vdoCont = document.querySelector('.video-player');
const vdo = vdoCont.querySelector('video');
vdo.addEventListener('play', () => {
console.log(this) // Here "this" refers to typescript class
this.updateVdoIcon(this);
});
vdo.addEventListener('pause', () => {
console.log(this) // Here "this" refers to typescript class
this.updateVdoIcon(this);
});
}
updateVdoIcon(videoElment: any) {
console.log(videoElment); // Expecting this to be video element instead of typescript class
}
我曾尝试将箭头函数更改为 JavaScript 函数,但在这里我无法使用我的 "updateVdoIcon" 函数。
vdo.addEventListener('play', function() {
this.updateVdoIcon(this); // Property 'updateVdoIcon' does not exist on type 'HTMLVideoElement'
});
我知道我可以使用匿名函数(如下所示)并在那里更新图标,但是如果我有很多代码想在函数中分开怎么办
vdo.addEventListener('play', function() {
this.paused ? console.log('Play icon') : console.log('Pause icon')
});
您可以在回调中传递 event.currentTarget
,这将是您定义事件侦听器的元素:
vdo.addEventListener('play', (event) => {
this.updateVdoIcon(event.currentTarget);
});
在您的代码段中,this
将是箭头函数中的 lexical this
。它从词法范围捕获 this
上下文,即 class 实例。
你可以试试这个方法,使用ElementRef
你可以访问元素然后绑定事件。
源代码来自: 答案。
import { AfterViewInit, Component, ElementRef} from '@angular/core';
constructor(private elementRef:ElementRef) {}
ngAfterViewInit() {
this.elementRef.nativeElement.querySelector('my-element')
.addEventListener('click', this.onClick.bind(this));
}
onClick(event) {
console.log(event);
}
调用事件侦听器处理程序时,它不是在组件范围内调用的。所以 this
不是 return 组件,而是控制元素。
你需要绑定你的监听器this
。
vdo.addEventListener('play', (function() {
this.updateVdoIcon(this);
}).bind(this));
参见文档 here。
您可以通过将其分离为函数调用 onClick 使其更清晰。
onClick() {
this.updateVdoIcon(this);
}
initialize() {
vdo.addEventListener('play', this.onClick.bind(this));
}
或者,您可以捕获 this
作为组件并传递给事件侦听器。
let self = this;
vdo.addEventListener('play', function() {
self.updateVdoIcon(this);
});
这是您的解决方案
ngAfterViewInit() {
const vdoCont = document.querySelector('.video-player');
const vdo = vdoCont.querySelector('video');
const that = this;
vdo.addEventListener('play', function(){
console.log(this) // Here "this" refers to typescript class
that.updateVdoIcon(this);
});
vdo.addEventListener('pause', function(){
console.log(this) // Here "this" refers to typescript class
that.updateVdoIcon(this);
});
}
updateVdoIcon(videoElment: 任何) {
console.log(videoElment); // 期望这是视频元素而不是打字稿 class
}
我正在尝试在切换视频时更改视频的自定义图标(Play/Pause)。
ngAfterViewInit() {
const vdoCont = document.querySelector('.video-player');
const vdo = vdoCont.querySelector('video');
vdo.addEventListener('play', () => {
console.log(this) // Here "this" refers to typescript class
this.updateVdoIcon(this);
});
vdo.addEventListener('pause', () => {
console.log(this) // Here "this" refers to typescript class
this.updateVdoIcon(this);
});
}
updateVdoIcon(videoElment: any) {
console.log(videoElment); // Expecting this to be video element instead of typescript class
}
我曾尝试将箭头函数更改为 JavaScript 函数,但在这里我无法使用我的 "updateVdoIcon" 函数。
vdo.addEventListener('play', function() {
this.updateVdoIcon(this); // Property 'updateVdoIcon' does not exist on type 'HTMLVideoElement'
});
我知道我可以使用匿名函数(如下所示)并在那里更新图标,但是如果我有很多代码想在函数中分开怎么办
vdo.addEventListener('play', function() {
this.paused ? console.log('Play icon') : console.log('Pause icon')
});
您可以在回调中传递 event.currentTarget
,这将是您定义事件侦听器的元素:
vdo.addEventListener('play', (event) => {
this.updateVdoIcon(event.currentTarget);
});
在您的代码段中,this
将是箭头函数中的 lexical this
。它从词法范围捕获 this
上下文,即 class 实例。
你可以试试这个方法,使用ElementRef
你可以访问元素然后绑定事件。
源代码来自:
import { AfterViewInit, Component, ElementRef} from '@angular/core';
constructor(private elementRef:ElementRef) {}
ngAfterViewInit() {
this.elementRef.nativeElement.querySelector('my-element')
.addEventListener('click', this.onClick.bind(this));
}
onClick(event) {
console.log(event);
}
调用事件侦听器处理程序时,它不是在组件范围内调用的。所以 this
不是 return 组件,而是控制元素。
你需要绑定你的监听器this
。
vdo.addEventListener('play', (function() {
this.updateVdoIcon(this);
}).bind(this));
参见文档 here。
您可以通过将其分离为函数调用 onClick 使其更清晰。
onClick() {
this.updateVdoIcon(this);
}
initialize() {
vdo.addEventListener('play', this.onClick.bind(this));
}
或者,您可以捕获 this
作为组件并传递给事件侦听器。
let self = this;
vdo.addEventListener('play', function() {
self.updateVdoIcon(this);
});
这是您的解决方案
ngAfterViewInit() {
const vdoCont = document.querySelector('.video-player');
const vdo = vdoCont.querySelector('video');
const that = this;
vdo.addEventListener('play', function(){
console.log(this) // Here "this" refers to typescript class
that.updateVdoIcon(this);
});
vdo.addEventListener('pause', function(){
console.log(this) // Here "this" refers to typescript class
that.updateVdoIcon(this);
});
}
updateVdoIcon(videoElment: 任何) { console.log(videoElment); // 期望这是视频元素而不是打字稿 class }