为什么我无法从这个事件处理函数内部访问这个正确初始化的 class 属性?
Why I can't access to this correctly initialized class property from the inside of this event handler function?
我发现 Angular\TypeScript 存在以下问题。
我有这个 class 来处理我的组件的行为:
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { EventService } from '../event.service';
import interactionPlugin, { Draggable } from '@fullcalendar/interaction';
interface WorkShiftTypes {
name: string;
value: string;
}
@Component({
selector: 'app-people-list',
templateUrl: './people-list.component.html',
styleUrls: ['./people-list.component.css']
})
export class PeopleListComponent implements OnInit {
people: any[];
//cities: City[];
workShiftTypes: WorkShiftTypes[];
selectedShift: WorkShiftTypes;
@ViewChild('draggable_people') draggablePeopleExternalElement: ElementRef;
constructor(private eventService: EventService) { }
ngOnInit(): void {
this.eventService.getPeople().then(people => {this.people = people;});
this.selectedShift = {name: 'Mattina', value: 'Mattina'};
this.workShiftTypes = [
{name: 'Mattina', value: 'Mattina'},
{name: 'Pomeriggio', value: 'Pomeriggio'},
{name: 'Notte', value: 'Notte'},
{name: 'Custom', value: 'Custom'}
];
}
ngAfterViewInit() {
console.log("PEOPLE LIST ngAfterViewInit() START !!!")
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
});
}
}
正如你在前面的代码中看到的那样,我有这个 属性:
selectedShift: WorkShiftTypes;
始终包含一个值(因为我将它设置为 ngOnInit() 挂钩方法的默认值,并且因为它绑定到我视图中的 PrimeNG 组件。
然后我有这个 ngAfterViewInit() 方法挂钩:
ngAfterViewInit() {
console.log("人员列表 ngAfterViewInit() 开始!!!")
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
});
我在这里创建一个 Draggable 对象,其中定义了拖动事件的回调函数(我从列表中拖动一个项目并将该项目放入日历中) .
此函数首先尝试将前一个 this.selectedShift class 属性 的值打印到控制台日志中,我正在尝试要使用此值向返回的对象添加一个字段,方法是:
selectedShift: this.selectedShift.value
在这两个操作上我遇到了问题。代码编译没有错误,但尝试执行我的应用程序,当我尝试从我的列表中拖动一个项目并将其放入我的日历时,我收到以下错误消息:
core.js:6272 ERROR TypeError: Cannot read property 'value' of undefined
at ExternalElementDragging.eventData [as suppliedDragMeta] (people-list.component.ts:48)
at ExternalElementDragging.push../node_modules/@fullcalendar/interaction/main.esm.js.ExternalElementDragging.buildDragMeta (main.esm.js:1916)
at EmitterMixin.ExternalElementDragging.handleDragStart (main.esm.js:1830)
at applyAll (main.esm.js:982)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.triggerWith (main.esm.js:3576)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.trigger (main.esm.js:3571)
at EmitterMixin.HitDragging.handleDragStart (main.esm.js:991)
at applyAll (main.esm.js:982)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.triggerWith (main.esm.js:3576)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.trigger (main.esm.js:3571)
在我看来,形成 **eventData: function(eventEl) { ...} 事件处理函数的内部,它无法访问我的 this.selectedShift class 属性(是因为在这种特定情况下 this 指的是 Draggable 对象吗?)。我很确定这一点,因为移动这条线:
console.log("SELECTED SHIFT: " + this.selectedShift.value);
在此函数之外(例如作为 **ngAfterViewInit() 挂钩函数的第一行)我检索了由 ngOnInit() 函数设置的正确默认值。所以这个值被正确初始化了。
为什么我无法从这个函数内部访问这个 属性?我怎样才能访问它并修复我的错误?
这是因为 eventData 处理程序的范围。
您没有使用箭头函数,因此 this
的上下文绑定到调用者。
您可能想改用箭头函数(箭头函数的上下文与其声明绑定):
eventData: (eventEl) => {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
另一种方法是使用绑定函数:
const handler = function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: handler.bind(this)
});
我发现 Angular\TypeScript 存在以下问题。
我有这个 class 来处理我的组件的行为:
import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
import { EventService } from '../event.service';
import interactionPlugin, { Draggable } from '@fullcalendar/interaction';
interface WorkShiftTypes {
name: string;
value: string;
}
@Component({
selector: 'app-people-list',
templateUrl: './people-list.component.html',
styleUrls: ['./people-list.component.css']
})
export class PeopleListComponent implements OnInit {
people: any[];
//cities: City[];
workShiftTypes: WorkShiftTypes[];
selectedShift: WorkShiftTypes;
@ViewChild('draggable_people') draggablePeopleExternalElement: ElementRef;
constructor(private eventService: EventService) { }
ngOnInit(): void {
this.eventService.getPeople().then(people => {this.people = people;});
this.selectedShift = {name: 'Mattina', value: 'Mattina'};
this.workShiftTypes = [
{name: 'Mattina', value: 'Mattina'},
{name: 'Pomeriggio', value: 'Pomeriggio'},
{name: 'Notte', value: 'Notte'},
{name: 'Custom', value: 'Custom'}
];
}
ngAfterViewInit() {
console.log("PEOPLE LIST ngAfterViewInit() START !!!")
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
});
}
}
正如你在前面的代码中看到的那样,我有这个 属性:
selectedShift: WorkShiftTypes;
始终包含一个值(因为我将它设置为 ngOnInit() 挂钩方法的默认值,并且因为它绑定到我视图中的 PrimeNG 组件。
然后我有这个 ngAfterViewInit() 方法挂钩:
ngAfterViewInit() { console.log("人员列表 ngAfterViewInit() 开始!!!")
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
});
我在这里创建一个 Draggable 对象,其中定义了拖动事件的回调函数(我从列表中拖动一个项目并将该项目放入日历中) .
此函数首先尝试将前一个 this.selectedShift class 属性 的值打印到控制台日志中,我正在尝试要使用此值向返回的对象添加一个字段,方法是:
selectedShift: this.selectedShift.value
在这两个操作上我遇到了问题。代码编译没有错误,但尝试执行我的应用程序,当我尝试从我的列表中拖动一个项目并将其放入我的日历时,我收到以下错误消息:
core.js:6272 ERROR TypeError: Cannot read property 'value' of undefined
at ExternalElementDragging.eventData [as suppliedDragMeta] (people-list.component.ts:48)
at ExternalElementDragging.push../node_modules/@fullcalendar/interaction/main.esm.js.ExternalElementDragging.buildDragMeta (main.esm.js:1916)
at EmitterMixin.ExternalElementDragging.handleDragStart (main.esm.js:1830)
at applyAll (main.esm.js:982)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.triggerWith (main.esm.js:3576)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.trigger (main.esm.js:3571)
at EmitterMixin.HitDragging.handleDragStart (main.esm.js:991)
at applyAll (main.esm.js:982)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.triggerWith (main.esm.js:3576)
at EmitterMixin.push../node_modules/@fullcalendar/core/main.esm.js.EmitterMixin.trigger (main.esm.js:3571)
在我看来,形成 **eventData: function(eventEl) { ...} 事件处理函数的内部,它无法访问我的 this.selectedShift class 属性(是因为在这种特定情况下 this 指的是 Draggable 对象吗?)。我很确定这一点,因为移动这条线:
console.log("SELECTED SHIFT: " + this.selectedShift.value);
在此函数之外(例如作为 **ngAfterViewInit() 挂钩函数的第一行)我检索了由 ngOnInit() 函数设置的正确默认值。所以这个值被正确初始化了。
为什么我无法从这个函数内部访问这个 属性?我怎样才能访问它并修复我的错误?
这是因为 eventData 处理程序的范围。
您没有使用箭头函数,因此 this
的上下文绑定到调用者。
您可能想改用箭头函数(箭头函数的上下文与其声明绑定):
eventData: (eventEl) => {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
另一种方法是使用绑定函数:
const handler = function(eventEl) {
console.log("DRAG !!!");
console.log("SELECTED SHIFT: " + this.selectedShift.value);
return {
title: eventEl.innerText,
selectedShift: this.selectedShift.value
};
}
new Draggable(this.draggablePeopleExternalElement.nativeElement, {
itemSelector: '.fc-event',
eventData: handler.bind(this)
});