为什么我无法从这个事件处理函数内部访问这个正确初始化的 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)
});