Cytoscape.js 单击节点时无法访问 class 变量和服务

Cytoscape.js cannot access class variables and services when node is clicked

我正在尝试将 Cytoscape.js 和 Angular7 结合起来参考下面的问题。

为了处理节点点击事件,我实现了cy.on()。 此功能有效,但无法访问 class 个变量或服务。

如何在 cy.on() 的本地函数中访问它们?

import { Component, OnInit } from '@angular/core';
import { Someservice } from './some.service'
declare var cytoscape: any;

@Component({
  selector: 'app-test',
  templateUrl: '<div id="cy"></div>',
  styleUrls: ['./test.component.scss']
})

let foobar:string = 'bar'

export class TestComponent implements OnInit {

  cy: any;
  foo:string = 'bar';

  constructor(private someservice: Someservice){}

  ngOnInit() {
      this.InitGraph()
      this.addListner()
  }

  NodeClicked(nodeid) {
      console.log(nodeid) //doesn't work
  }

  addListner(){
    this.cy.on('tap', 'node', function(evt){
      var node = evt.target;
      console.log( 'tapped ' + node.id() ); //this works
      console.log(this.foo) //doesn't work and "undefined" is shown
      this.NodeClicked(node.id()) //doesn't work and "this.NodeClicked is not function" is shown
      this.someservice.somefunc(node.id()) // doesn't work and "somefunc" is not defined is shown.
      console.log(foobar) // this work
    });
  }

  InitGraph(){
    this.cy = cytoscape({
      container: document.getElementById('cy'),

      elements: [
        { data: { id: 'a' } },
        { data: { id: 'b' } },
        {
          data: {
            id: 'ab',
            source: 'a',
            target: 'b'
          }
        }]
    });
  }
}

因为您在 this.cy.on 方法的回调中使用了 function 关键字,所以 this 关键字将被设置为全局对象(可能 window ) (如果你不在严格模式下)或 undefined (如果你在严格模式下)。或者,它可以由 cytoscape 本身设置为不同的值。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#Function_context

cytoscape 源表明在这种情况下 this 被设置为其他值。 https://github.com/cytoscape/cytoscape.js/blob/2205c12fe4c6925a1727d7387c84e12b169c1a9e/src/emitter.js#L219

您应该可以通过两种方式获取组件的 this 值:

选项 1

使用箭头函数作为回调函数,与箭头函数一样,this 保留封闭词法上下文 this 的值。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#Arrow_functions

addListner(){
  this.cy.on('tap', 'node', e => {
    var node = e.target;
    console.log('tapped ' + node.id());
    console.log(this.foo);
  }
}

选项 2

在您的组件上调用一个新方法,因为在本例中 this 设置为调用该方法的对象 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#As_an_object_method

addListner(){
  this.cy.on('tap', 'node', e => this.onNodeClicked(e));
}

onNodeClicked(e) {
  var node = e.target;
  console.log('tapped ' + node.id());
  console.log(this.foo);
}