D3. js теряет ссылку на объект в событиях "on" - PullRequest
1 голос
/ 27 января 2020

Мне нужна помощь в понимании того, что происходит в моем маленьком коде. В моем веб-приложении я использую D3. js для рисования фигур, которые я называю маркерами . Маркер можно перетаскивать по экрану, и при каждом перетаскивании я беру его позицию, делаю некоторые вычисления и обновляю объект данных, назначенный этому маркеру. Позвольте мне показать вам:

class Marker {
  constructor(name) {
    this.name = name;
    this.computedStuff = 0;
  }

  getDisplayName() {
    return 'Marker ' + this.name;
  }
}

this.markerValues = {
  'm1': new Marker('m1'),
  'm2': new Marker('m2')
}

this.svg.selectAll('g.marker')
        .data(_.values(this.markerValues))
        .join(enter => {
          const group = enter.append('g');

          group.append('path')
              .attr('d', 'M -12.867771,6.1070093 V 13.761566 H 12.867771 '
                  + 'V 6.1070093 H 6.4338855 '
                  + 'L 0,-1.1321257 -6.4338856,6.1070093 Z')
              .attr('transform', `translate(0 120) scale(2)`)
              .attr('stroke', 'black')
              .attr('stroke-width', '1px')
              .attr('fill', '#fff')
              .on('dblclick', d => console.log(d));

          group.append('text')
              .attr('y', 120)
              .text(d => d.getDisplayName())
              .style('font-size', '10px')
              .style('fill', 'black');

          return group;
        })
        .attr('class', 'marker')
        .call(d3.drag()
            .on('drag', function (d) {
              // Computation here

              d.computedStuff = computedAbove;

              // Here is a typical code for moving a marker according to 
              // d3.event.
            })
        );

Проблема заключается в следующем: .on('dblclick', d => console.log(d));. Это выглядит довольно просто - при двойном щелчке зарегистрируйте содержимое данных; и это "работает" хорошо, пока я не переместу маркер. Когда маркер перемещается, переменная computedStuff изменяется из-за вычислений, но последующие двойные щелчки по пути записывают старое значение в консоли, как будто объект вообще не изменялся. Я на 100% уверен, что он изменился, потому что я проверил содержимое объекта this.markerValues. Выглядит так, как будто к обработчику событий была прикреплена копия объекта, и он записывает копию вместо исходного объекта.

Но ...

Когда я удаляю этот обработчик событий из пути и присоедините его к группе: group.on('dblclick', d => console.log(d));, тогда это работает! Я могу переместить маркер, дважды щелкнуть его, и мне всегда будет предоставлено правильное значение.

Почему обработчику группы всегда предоставляются действительные данные, тогда как обработчик, прикрепленный к дочернему элементу группы, сохраняет какой-то вид копии или объекта, на который нет ссылок?

1 Ответ

0 голосов
/ 28 января 2020

Простое решение: не используйте жирную стрелку .on('dblclick', d => console.log(d));

Вместо этого используйте классические обозначения

.on('dblclick', function(d) { console.log(d) });

d3 задает область действия this в обработчике для ссылки к указанному узлу. Использование жирных стрелок перекрывает лексическую область видимости.

Однако вы можете использовать жирные стрелки в вашем обработчике, если вы используете полную сигнатуру обработчика и ссылаетесь на текущие узлы по индексу:

selection.on('dblclick', (d, i, nodes) => {
  console.log(nodes[i])
});

В есть приличное объяснение статья

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...