d3 v4 извлекает DOM-объект перетаскивания из обратного вызова перетаскивания, когда `this` недоступно

Документация для d3.drag гласит, что цель элемента DOM события перетаскивания будет доступна в this на обратный вызов:

Когда указанное событие отправляется, каждый слушатель будет вызываться с тем же контекстом и аргументами, что и слушатели selection.on: текущий набор данных d и индекс i с контекстом this в качестве текущего элемента DOM.

Но мой обратный вызов является экземпляром объекта и this указывает на этот объект. Поэтому мне нужен другой способ доступа к текущему элементу DOM, который обычно передается в this, Как мне это сделать?

1 ответ

Решение

Используйте второй и третий аргументы вместе, чтобы получить this когда this не доступен:

d3.drag().on(typename, function(d, i, n) {
  //here, 'this' is simply n[i]
})

Для подробного объяснения, посмотрите на статью ниже, которую я написал, чтобы иметь дело с this в функции стрелок. Вопрос отличается от вашего, но объяснение такое же.

Вот базовая демонстрация, попробуйте перетащить круг и посмотреть на консоль:

var data = d3.range(5)
var svg = d3.select("body")
  .append("svg")
  .attr("width", 400)
  .attr("height", 100);
var circle = svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cy", 50)
  .attr("cx", function(d) {
    return 50 + 50 * d
  })
  .attr("r", 10)
  .attr("fill", "tan")
  .attr("stroke", "black")
  .call(d3.drag()
    .on("start", function(d, i, n) {
      console.log(JSON.stringify(n[i]))
    }))
<script src="https://d3js.org/d3.v4.min.js"></script>

PS: я использую JSON.stringify на выбор D3, потому что фрагменты стека зависают, если вы пытаетесь console.log выбор D3.


Использование "this" с функцией стрелки

Большинство функций в D3.js принимают анонимную функцию в качестве аргумента. Общие примеры .attr, .style, .text, .on а также .data, но список намного больше, чем это.

В таких случаях анонимная функция оценивается для каждого выбранного элемента в следующем порядке:

  1. Текущее значение (d)
  2. Текущий индекс (i)
  3. Текущая группа (nodes)
  4. this в качестве текущего элемента DOM.

Данные, индекс и текущая группа передаются в качестве аргументов, известный первый, второй и третий аргументы в D3.js (чьи параметры традиционно называются d, i а также p в D3 v3.x). Для использования this Однако не нужно использовать аргумент:

.on("mouseover", function(){
    d3.select(this);
});

Приведенный выше код выберет this когда мышь находится над элементом. Проверьте это, работая в этой скрипке: https://jsfiddle.net/y5fwgopx/

Функция стрелки

Как новый синтаксис ES6, функция стрелки имеет более короткий синтаксис по сравнению с выражением функции. Тем не менее, для программиста D3, который использует this постоянно возникает ловушка: функция стрелки не создает свою собственную this контекст. Это означает, что в функции стрелки this имеет свое первоначальное значение из окружающего контекста.

Это может быть полезно в нескольких обстоятельствах, но это проблема для программиста, привыкшего использовать this в D3. Например, используя тот же пример в скрипте выше, это не будет работать:

.on("mouseover", ()=>{
    d3.select(this);
});

Если вы сомневаетесь, вот скрипка: https://jsfiddle.net/tfxLsv9u/

Ну, это не большая проблема: можно просто использовать обычное, старомодное выражение функции при необходимости. Но что, если вы хотите написать весь свой код, используя функции стрелок? Можно ли иметь код с функциями стрелок и при этом правильно использовать this в D3?

Второй и третий аргументы объединены

Ответ да, потому что this это то же самое из nodes[i], Подсказка фактически присутствует во всем D3 API, когда она описывает это:

...с this как текущий элемент DOM (nodes[i])

Объяснение простое: с nodes текущая группа элементов в DOM и i индекс каждого элемента, nodes[i] обратитесь к самому текущему элементу DOM. То есть, this,

Поэтому можно использовать:

.on("mouseover", (d, i, nodes) => {
    d3.select(nodes[i]);
});

И вот соответствующая скрипка: https://jsfiddle.net/2p2ux38s/

Другие вопросы по тегам