分組元素
- 當(dāng)執(zhí)行select/selectAll時(shí)候, 都會(huì)返回一個(gè)分組. 例如, 我們執(zhí)行代碼:
console.log(d3.select('body')._groups)
console.log(d3.selectAll('h2')._groups);
則展示:
4.PNG
當(dāng)我們執(zhí)行style/attr時(shí)候, 會(huì)對(duì)分組中的每個(gè)元素執(zhí)行. 而select只會(huì)匹配第一個(gè)元素, selectAll會(huì)匹配所有的元素.
- 每個(gè)元素均由父元素. 在返回分組時(shí)候, 可通過(guò)父元素確定元素的具體位置.
假設(shè)我們執(zhí)行操作:
const h = d3.selectAll('h2').append('p');
console.log(d3.selectAll('h2').selectAll('p'));
這里, 每個(gè)h2下面均由p. 如果我們d3.selectAll('h2').selectAll('p'), 則p會(huì)是一個(gè)分組, 但不在一個(gè)h2下, 而是在不同的h2下. 我們可以通過(guò)_parents屬性查知.
5.PNG
- 空元素用于表明缺失的元素. 假設(shè)我們?nèi)齻€(gè)h2, 但是只有前兩個(gè)h2存在p. 那么執(zhí)行如下代碼:
console.log(d3.selectAll('h2').selectAll('p'));
則顯示第三個(gè)元素為空數(shù)組:
6.PNG
數(shù)據(jù)綁定
- 數(shù)據(jù)是DOM元素的屬性, 而非選擇器的屬性. 數(shù)據(jù)可通過(guò)三種方式寫(xiě)入DOM屬性中:
- 通過(guò)selection.data(插入分組)
- 通過(guò)selection.datum(單個(gè)元素)
- 通過(guò)append, insert, 或者select, 從父級(jí)中繼承.
d3.select('body').datum(42);
console.log(document.body.__data__); // 42
// 通過(guò)父級(jí)繼承
d3.select('body').datum(42).append('h1');
console.log(d3.select('h1')._groups[0][0].__data__);// 42
- selection.data函數(shù)定義的是分組的數(shù)據(jù)而非具體元素的數(shù)據(jù).
key函數(shù)
-
使用selection.data時(shí)候, data和element的對(duì)應(yīng)是默認(rèn)通過(guò)索引的(數(shù)組的索引).
7.PNG - 如果數(shù)據(jù)是數(shù)組, 索引是高效的. 但是如果數(shù)據(jù)中的元素是字典, 則默認(rèn)使用索引則是低效的. 這時(shí)候, 需要我們指定key函數(shù).
const letters = [
{name: "A", frequency: .08167},
{name: "B", frequency: .01492},
{name: "C", frequency: .02780},
{name: "D", frequency: .04253},
{name: "E", frequency: .12702}
];
const div = d3.select('.chart');
div.selectAll('div').data(letters, d => d.name)
.enter().append('div')
.text(d => d.name);
Enter, Update和Exit
- 當(dāng)插入數(shù)據(jù)情況下, 一般會(huì)有三種邏輯操作
- Update: 給定的數(shù)據(jù)中, 存在對(duì)應(yīng)的DOM元素. (selection.data)
- Enter: 給定的數(shù)據(jù)中, 沒(méi)有對(duì)應(yīng)的DOM元素. (selection.enter)
- Exit: 給定的DOM元素中, 沒(méi)有對(duì)應(yīng)的數(shù)據(jù). (selection.exit)
考慮以下情況: 新建元素abcde, 然后更新為yeaoi.
const div = d3.select('.chart');
div.selectAll('p').data(['a', 'b', 'c', 'd', 'e'])
.enter().append('p')
.text(d => d);
const newDiv = div.selectAll('p').data(['y', 'e', 'a', 'o', 'i'], d => d);
newDiv.enter().append('p')
.text(d => d);
newDiv.exit().remove();
- key函數(shù)d => d必須填寫(xiě). 如果不填寫(xiě), 則為新增p元素. 填寫(xiě)的情況下, 匹配之前的p元素.
- 使用enter新建DOM元素.
- 使用exit找出存在DOM元素, 但是數(shù)據(jù)不提供的(如b, c, d三元素), 然后刪除它們.