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
, но список намного больше, чем это.
В таких случаях анонимная функция оценивается для каждого выбранного элемента в следующем порядке:
- Текущее значение (
d
) - Текущий индекс (
i
) - Текущая группа (
nodes
) 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/