Czy ktoś może wyjaśnić różnicę między datum () a data () w D3.js? Widzę, że oba są używane i nie jestem pewien, dlaczego powinieneś wybrać jedno z nich?
Czy ktoś może wyjaśnić różnicę między datum () a data () w D3.js? Widzę, że oba są używane i nie jestem pewien, dlaczego powinieneś wybrać jedno z nich?
Odpowiedzi:
Znalazłem tutaj poprawną odpowiedź od samego Mike'a:
D3 - jak radzić sobie ze strukturami danych JSON?
Jeśli chcesz powiązać swoje dane z jednym elementem SVG, użyj
(...).data([data])
lub
(...).datum(data)
Jeśli chcesz powiązać swoje dane z wieloma elementami SVG
(...).data(data).enter().append("svg")
.....
enter()
, d3 wiąże resztę elementów tablicy z nowo utworzonymi elementami SVG.
Po dokładnym przyjrzeniu się temu stwierdziłem, że odpowiedzi tutaj na SO nie są kompletne, ponieważ obejmują one tylko przypadek, gdy wywołujesz selection.data
i selection.datum
z data
parametrem wejściowym . Nawet w tym scenariuszu oba zachowują się inaczej, jeśli zaznaczenie jest pojedynczym elementem, a jeśli zawiera wiele elementów. Co więcej, obie te metody można również wywoływać bez żadnych argumentów wejściowych w celu przeszukiwania powiązanych danych / danych w zaznaczeniu, w którym to przypadku ponownie zachowują się inaczej i zwracają różne rzeczy.
Edit - napisałem nieco bardziej szczegółową odpowiedź na to pytanie tutaj , ale post poniżej dość dużo przechwytuje wszystkie najważniejsze punkty dotyczące tych dwóch metod i jak różnią się one od siebie.
Podając data
jako argument wejściowy
selection.data(data)
dokładają wszelkich starań, aby wykonać dane dołącz pomiędzy elementami data
tablicy z wyboru, w wyniku utworzenia enter()
, exit()
oraz update()
pozycje, które można następnie operować. Efektem końcowym tego jest, jeśli przejdziesz do tablicy data = [1,2,3]
, podejmowana jest próba połączenia każdego elementu danych (tj. Układu odniesienia) z zaznaczeniem. Każdy element zaznaczenia będzie miał związany tylko jeden element odniesienia data
.
selection.datum(data)
całkowicie pomija proces łączenia danych. To po prostu przypisuje całość data
wszystkim elementom zaznaczenia jako całości, bez dzielenia go, jak w przypadku łączenia danych. Więc jeśli chcesz powiązać całą tablicę data = [1, 2, 3]
z każdym elementem DOM w twoim selection
, wtedy selection.datum(data)
to osiągniesz.
Ostrzeżenie: wiele osób uważa, że
selection.datum(data)
jest to równoważne,selection.data([data])
ale jest to prawdą tylko wtedy, gdyselection
zawiera jeden element . Jeśliselection
zawiera wiele elementów DOM, wówczasselection.datum(data)
wiąże całość zdata
każdym elementem w zaznaczeniu. W przeciwieństwie,selection.data([data])
wiąże tylko całość zdata
pierwszym elementem wselection
. Jest to zgodne z zachowaniem łączenia danychselection.data
.
Gdy nie data
podajesz argumentu wejściowego
selection.data()
weźmie powiązane dane dla każdego elementu w zaznaczeniu i połączy je w zwracaną tablicę. Tak więc, jeśli selection
składa się z 3 elementów DOM z danymi "a"
, "b"
a "c"
połączone ze sobą odpowiednio selection.data()
zwrotów ["a", "b", "c"]
. Ważne jest, aby zauważyć, że jeśli selection
jest to pojedynczy element z (na przykład) "a"
związaną z nim datum , wówczas selection.data()
powróci ["a"]
i nie będzie, "a"
jak niektórzy mogą się spodziewać.
selection.datum()
ma sens tylko dla pojedynczego zaznaczenia, ponieważ jest zdefiniowany jako powrót układu odniesienia związanego z pierwszym elementem zaznaczenia. Tak więc w powyższym przykładzie z wyboru składający się z elementów DOM ze związanym z odniesienia "a"
, "b"
i "c"
, selection.datum()
po prostu wrócić "a"
.
Zauważ, że nawet jeśli
selection
ma jeden elementselection.datum()
iselection.data()
zwracaj różne wartości. Pierwszy zwraca związany punkt odniesienia dla wyboru ("a"
w powyższym przykładzie), podczas gdy drugi zwraca związany punkt odniesienia w tablicy (["a"]
w powyższym przykładzie).
Mam nadzieję, że to pomaga wyjaśnić, w jaki sposób selection.data
i selection.datum()
różnią się od siebie zarówno w przypadku udostępniania danych jako argument wejściowy i podczas odpytywania dla związanego odniesienia nie dostarczając żadnych argumentów wejściowych.
PS - Najlepszym sposobem na zrozumienie, jak to działa, jest rozpoczęcie od pustego dokumentu HTML w Chrome i otwarcie konsoli i próba dodania kilku elementów do dokumentu, a następnie rozpoczęcie wiązania danych za pomocą selection.data
i selection.datum
. Czasami o wiele łatwiej „coś” zrobić, robiąc, niż czytając.
Oto kilka dobrych linków:
Dobra dyskusja na temat D3 „data ()”: zrozumienie, w jaki sposób D3.js wiąże dane z węzłami
Zgodnie z tym ostatnim:
# selection.data([values[, key]])
Łączy podaną tablicę danych z bieżącym wyborem. Podane wartości to tablica wartości danych, na przykład tablica liczb lub obiektów, lub funkcja zwracająca tablicę wartości.
...
# selection.datum([value])
Pobiera lub ustawia powiązane dane dla każdego wybranego elementu. W przeciwieństwie do metody selection.data, ta metoda nie oblicza złączenia (a zatem nie oblicza wejść i wyjść z selekcji).
Myślę, że wyjaśnienie podane przez HamsterHuey jest jak dotąd najlepsze. Aby go rozwinąć i przedstawić wizualnie różnice, stworzyłem przykładowy dokument, który ilustruje przynajmniej część różnic między data
i datum
.
Poniższa odpowiedź jest bardziej opinią wynikającą z zastosowania tych metod, ale cieszę się, że mogę je poprawić, jeśli się mylę.
Ten przykład można uruchomić poniżej lub w tym skrzypce .
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
Myślę, że datum
łatwiej jest to uchwycić, ponieważ nie wykonuje łączenia, ale oczywiście oznacza to również, że ma różne przypadki użycia.
Dla mnie jedną wielką różnicą - choć jest ich więcej - to fakt, że data
jest to naturalny sposób wykonywania aktualizacji (na żywo) na wykresie d3, ponieważ cały wzorzec wchodzenia / aktualizowania / wychodzenia sprawia, że jest to proste, gdy tylko je dostaniesz.
datum
z drugiej strony wydaje mi się, że lepiej nadaje się do przedstawień statycznych. W poniższym przykładzie mogę na przykład osiągnąć ten sam wynik, zapętlając oryginalną tablicę i uzyskując dostęp do danych przez indeks w ten sposób:
data.map((n, i) => {
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node-${n} => data: ${d[i]}`);
});
Wypróbuj tutaj: https://jsfiddle.net/gleezer/e4m6j2d8/6/
Ponownie myślę, że jest to o wiele łatwiejsze do uchwycenia, ponieważ uwalniasz się od mentalnego obciążenia wynikającego ze schematu wchodzenia / aktualizowania / wychodzenia, ale gdy tylko będziesz musiał zaktualizować lub zmienić wybór, na pewno lepiej będzie się uciekać .data()
.
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
/* Ignore all the css */
html {
font-family: arial;
}
.l {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin: 10px 0;
}
.l-a {
background: #cf58e4;
}
.l-b {
background: #42e4e4;
}
.a {
border-bottom: 2px solid #cf58e4;
}
.b {
border-bottom: 2px solid #42e4e4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
<div style="margin-bottom: 20px;">
<span class="l l-a"></span> .datum() <br />
<span class="l l-b"></span> .data()
</div>
<div id="root"></div>