Ai đó có thể vui lòng giải thích sự khác biệt giữa datum () và data () trong D3.js không? Tôi thấy cả hai đang được sử dụng và tôi không chắc tại sao bạn nên chọn cái này hơn cái kia?
Ai đó có thể vui lòng giải thích sự khác biệt giữa datum () và data () trong D3.js không? Tôi thấy cả hai đang được sử dụng và tôi không chắc tại sao bạn nên chọn cái này hơn cái kia?
Câu trả lời:
Tôi tìm thấy câu trả lời chính xác ở đây từ chính Mike:
D3 - làm thế nào để đối phó với các cấu trúc dữ liệu JSON?
Nếu bạn muốn liên kết dữ liệu của mình với một yếu tố SVG, hãy sử dụng
(...).data([data])
hoặc là
(...).datum(data)
Nếu bạn muốn liên kết dữ liệu của mình với nhiều yếu tố SVG
(...).data(data).enter().append("svg")
.....
enter()
, d3 sẽ liên kết phần còn lại của phần tử mảng với phần tử SVG mới được tạo.
Sau khi xem xét điều này một chút, tôi thấy rằng các câu trả lời ở đây trên SO không đầy đủ vì chúng chỉ bao gồm trường hợp khi bạn gọi selection.data
và selection.datum
với một data
tham số đầu vào . Ngay cả trong kịch bản đó, cả hai hành xử khác nhau nếu lựa chọn là một yếu tố duy nhất so với khi nó chứa nhiều yếu tố. Hơn nữa, cả hai phương thức này cũng có thể được gọi mà không có bất kỳ đối số đầu vào nào để truy vấn dữ liệu / mốc dữ liệu bị ràng buộc trong lựa chọn, trong trường hợp chúng một lần nữa hành xử khác nhau và trả về những thứ khác nhau.
Chỉnh sửa - Tôi đã đăng một câu trả lời chi tiết hơn một chút cho câu hỏi này ở đây , nhưng bài đăng dưới đây nắm bắt được tất cả các điểm chính liên quan đến hai phương pháp và cách chúng khác nhau.
Khi cung cấp data
làm đối số đầu vào
selection.data(data)
sẽ cố gắng thực hiện một dữ liệu tham gia giữa các yếu tố của data
mảng với các lựa chọn kết quả trong việc tạo ra enter()
, exit()
và update()
các lựa chọn mà bạn sau đó có thể hoạt động trên. Kết quả cuối cùng của điều này là nếu bạn truyền vào một mảng data = [1,2,3]
, một nỗ lực được thực hiện để nối từng phần tử dữ liệu riêng lẻ (tức là mốc) với lựa chọn. Mỗi phần tử của lựa chọn sẽ chỉ có một phần tử chuẩn duy nhất được data
liên kết với nó.
selection.datum(data)
bỏ qua quá trình tham gia dữ liệu hoàn toàn. Điều này chỉ đơn giản là gán toàn bộ data
cho tất cả các thành phần trong vùng chọn mà không tách nó ra như trong trường hợp nối dữ liệu. Vì vậy, nếu bạn muốn liên kết toàn bộ một mảng data = [1, 2, 3]
với mọi thành phần DOM trong của bạn selection
, thì selection.datum(data)
sẽ đạt được điều này.
Cảnh báo: Nhiều người cho rằng điều đó
selection.datum(data)
tương đươngselection.data([data])
nhưng điều này chỉ đúng nếuselection
chứa một yếu tố duy nhất . Nếuselection
chứa nhiều phần tử DOM, thìselection.datum(data)
sẽ liên kết toàn bộdata
với mọi phần tử trong phần chọn. Ngược lại,selection.data([data])
chỉ liên kết toàn bộdata
với phần tử đầu tiên trongselection
. Điều này phù hợp với hành vi tham gia dữ liệu củaselection.data
.
Khi cung cấp không có data
đối số đầu vào
selection.data()
sẽ lấy mốc thời gian ràng buộc cho từng thành phần trong vùng chọn và kết hợp chúng thành một mảng được trả về. Vì vậy, nếu bạn selection
bao gồm 3 yếu tố DOM với dữ liệu "a"
, "b"
và "c"
bị ràng buộc với nhau tương ứng, selection.data()
lợi nhuận ["a", "b", "c"]
. Điều quan trọng cần lưu ý là nếu selection
là một phần tử duy nhất với (bằng ví dụ) thì mốc chuẩn "a"
bị ràng buộc với nó, sau đó selection.data()
sẽ trả về ["a"]
và không "a"
như một số người có thể mong đợi.
selection.datum()
chỉ có ý nghĩa đối với một lựa chọn vì nó được định nghĩa là trả về mốc chuẩn bị ràng buộc với phần tử đầu tiên của lựa chọn. Vì vậy, trong ví dụ trên với lựa chọn bao gồm các phần tử DOM với dữ kiện ràng buộc của "a"
, "b"
và "c"
, selection.datum()
chỉ đơn giản là sẽ quay trở lại "a"
.
Lưu ý rằng ngay cả khi
selection
có một phần tử duy nhấtselection.datum()
vàselection.data()
trả về các giá trị khác nhau. Cái trước trả về mốc dữ liệu bị ràng buộc cho lựa chọn ("a"
trong ví dụ ở trên) trong khi cái sau trả về mốc dữ liệu bị ràng buộc trong một mảng (["a"]
trong ví dụ trên).
Hy vọng rằng điều này sẽ giúp làm rõ cách thức selection.data
và selection.datum()
khác biệt với nhau cả khi cung cấp dữ liệu dưới dạng đối số đầu vào và khi truy vấn dữ liệu bị ràng buộc bằng cách không cung cấp bất kỳ đối số đầu vào nào.
PS - Cách tốt nhất để hiểu cách thức hoạt động của nó là bắt đầu với một tài liệu HTML trống trong Chrome và mở bảng điều khiển và thử thêm một vài yếu tố vào tài liệu và sau đó bắt đầu ràng buộc dữ liệu bằng cách sử dụng selection.data
và selection.datum
. Đôi khi, thật dễ dàng để "mò mẫm" một cái gì đó bằng cách làm hơn là đọc.
Dưới đây là một số liên kết tốt:
Thảo luận tốt về "dữ liệu ()" của D3: Hiểu cách D3.js liên kết dữ liệu với các nút
Mỗi cái sau:
# selection.data([values[, key]])
Tham gia mảng dữ liệu đã chỉ định với lựa chọn hiện tại. Các giá trị được chỉ định là một mảng các giá trị dữ liệu, chẳng hạn như một mảng các số hoặc đối tượng hoặc một hàm trả về một mảng các giá trị.
...
# selection.datum([value])
Nhận hoặc đặt dữ liệu ràng buộc cho từng thành phần được chọn. Không giống như phương thức select.data, phương thức này không tính toán một phép nối (và do đó không tính toán các lựa chọn nhập và thoát).
Tôi nghĩ rằng lời giải thích được đưa ra bởi HamsterHuey là tốt nhất cho đến nay. Để mở rộng về nó và đưa ra một đại diện trực quan về sự khác biệt, tôi đã tạo một tài liệu mẫu minh họa ít nhất một phần của sự khác biệt giữa data
và datum
.
Câu trả lời dưới đây có nhiều ý kiến xuất phát từ việc sử dụng các phương pháp này, nhưng tôi rất vui khi được sửa nếu tôi sai.
Ví dụ này có thể được chạy bên dưới hoặc trong Fiddle này .
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}`)
Tôi nghĩ rằng datum
việc nắm bắt đơn giản hơn vì nó không tham gia, nhưng tất nhiên điều này cũng có nghĩa là nó có các trường hợp sử dụng khác nhau.
Đối với tôi một sự khác biệt lớn - mặc dù có nhiều hơn - đó là thực tế data
chỉ là cách tự nhiên (trực tiếp) cập nhật trên biểu đồ d3, vì toàn bộ mô hình nhập / cập nhật / thoát làm cho nó đơn giản, một khi bạn có được nó.
datum
mặt khác, dường như tôi phù hợp hơn cho các biểu diễn tĩnh. Trong ví dụ dưới đây, ví dụ tôi có thể đạt được kết quả tương tự vòng lặp của mình trên mảng ban đầu và truy cập dữ liệu theo chỉ mục như vậy:
data.map((n, i) => {
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node-${n} => data: ${d[i]}`);
});
Dùng thử tại đây: https://jsfiddle.net/gleezer/e4m6j2d8/6/
Một lần nữa, tôi nghĩ rằng cách này dễ nắm bắt hơn khi bạn không phải chịu gánh nặng tinh thần đến từ mẫu nhập / cập nhật / thoát, nhưng ngay khi bạn cần cập nhật hoặc thay đổi lựa chọn, bạn chắc chắn sẽ tốt hơn khi dùng đến .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>