D3JsDay10 遇到元素资料不相等,用函式解决高人一等

绑定的资料和画面上的元素不相等

enter()函式—没放入元素的资料

先看以下程序码

<body>
  <div></div>
  <div></div>
  <script>
    const arr = [13,6,2,34,23];
    const div = d3.select("body").selectAll("div");
    console.log(div.data(arr));
    div.data(arr).text(function(d) { return d});
  </script>
</body>

这时候你尝试着开启开发者人工具的会发现有一个叫做_enter的阵列里面元素前两个是empty和後面三个Ut的物件,由於你所选取的div只有两个,当资料被添加进去div的时候会有两个如愿地加进div然而剩下三个并没有被加入进去的就会在_enter阵列里面呈现。

画面如下图
https://ithelp.ithome.com.tw/upload/images/20210925/20125095gqrV3Nvaqi.png

这时候你可以发现网页只有前两个资料被显示在画面上

https://ithelp.ithome.com.tw/upload/images/20210925/20125095dGlja4bl0r.png

因此这时候我们可以使用enter()这个方法来获取那些未被添加至div的资料进行操作,我们尝试着将程序码改成以下片段

const arr = [13,6,2,34,23];
const div =d3.select("body").selectAll("div");
div.data(arr).enter().append("div").text(function(d) { return d});

这个时候画面可以渲染出未被放入起始div的资料

https://ithelp.ithome.com.tw/upload/images/20210925/20125095UNs8EHlMkH.png

因此我们将程序码改成如下

let arr = [13,6,2,34,23];
let div =d3.select("body").selectAll("div");
div.data(arr).text(function(d){return d});
div.data(arr).enter().append("div").text(function(d) { return d});

原先的程序码将在div.data(arr)添加enter()的方法後再添加div最後同样地用text()把资料显示在画面上,如下图
https://ithelp.ithome.com.tw/upload/images/20210925/20125095CFm3zSYvLP.png
因此我们可以结合上面的程序码就能正确的渲染出画面

我们可以看下图一般使用data()绑定元素的时候如果原先画面有div会被正确对应,如果没有被对应到的会被归类到enter里面,这时候我们就用enter函式来append div元素就可以渲染出整个画面

https://ithelp.ithome.com.tw/upload/images/20210925/201250958QGrq3LcXd.png

另外官方API文件enter()的说明有提到可以使用merge()合并,下个部分会提到关於merge()的应用。

https://ithelp.ithome.com.tw/upload/images/20210925/201250953SnD9KFOCh.png

官方enter()文件参考

merge()函式—合并

使用merge把原先body里面有的div和後来透过append()添加的div进行合并,我们宣告一个merge做为起点来操作画面,如下程序码

let arr = [13,6,2,34,23];
let div =d3.select("body").selectAll("div");
let merge = div.data(arr)
               .merge(
                 div.data(arr)
                 .enter()
                 .append("div")
                );
  console.log(merge);
  merge.text(function(d) {return d});

这时候你开启开发人员工具的时候就比较像是当初你在body拥有5个div一样了,此时我们加入text()函式就能完整的显示出arr阵列里面的内容在网页上。

https://ithelp.ithome.com.tw/upload/images/20210925/20125095WkQPM1T3gQ.png

exit()函式—没资料放入的元素

前面的例子提到当资料大於画面中的元素时候使用enter()选取来补足,反之如果当资料量小於画面中的元素的时候,我们可以使用exit()函式来选取通常也伴随着remove()函式来移除多余的这些元素,来看以下的例子。

<body>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
<script>
  const arr = [13,6,2,34,23];
  const div =d3.select("body").selectAll("div");
  const dataInDiv = div.data(arr);
  dataInDiv.text(function(d){return d})
  dataInDiv.exit().remove();
</script>

exit()官方API文件
可以参照官方API文件说明

这时候你开启开发者人员工具可以发现原本你写六个div,因为撰写了dataInDiv.exit().remove(),把没有绑定资料的div给移除了。

https://ithelp.ithome.com.tw/upload/images/20210925/20125095HPuYeQrL3E.png

如下图如果资料绑定的过程当中有多余的元素时会被归类在exit里面,这时候可以使用remove来移除多余的元素。

https://ithelp.ithome.com.tw/upload/images/20210925/20125095SFVb4ckczG.png

join()函式—三个愿望一次满足

由於我们可能不确定元画面上的元素和资料哪个数量比较大,因此在撰写资料到元素时,我们会用上述的方法来确保的数量是相等,不会有元素大於资料或者资料大於元素的情况,参照以下程序码

<body>
  <div></div>
  <div></div>
  <script>
    const arr = [13, 6, 2, 34, 23];
    const div = d3.select("body").selectAll("div");
    const dataInDiv = div.data(arr);
    const merge = div.data(arr)
                   .merge(dataInDiv.enter()
                                   .append("div")
                          );
    merge.text(function (d) {
      return d;
    });
    dataInDiv.exit().remove();
  </script>
</body>

撰写如上述的程序码後,无论画面上原本的div数量是两个或是六个并不会造成资料缺失或是元素过多的情形。
然而这些操作对於新手不友善,并且繁琐,所幸後来的版本增加了一个函式叫做join()接下来你可以尝试着使用下列程序码。

  let arr = [13, 6, 2, 34, 23];
  let div = d3.select("body").selectAll("div");
  let dataInDiv = div.data(arr);
  let join = dataInDiv.join("div");
  join.text(function (d) { return d});

顿时你会觉得世界的美好,官方API说明他将会合并enter和绑定资料的selection甚至移除多余的部分

官方API文件JOIN()

参考以下官方API截图
https://ithelp.ithome.com.tw/upload/images/20210925/20125095fYdmGLqKnm.png


<<:  【在厨房想30天的演算法】Day 10 资料结构:树 Tree

>>:  [Day25] 程序码重构

OpenStack Cinder 介绍

本系列文章同步发布於笔者网站 今天我们要来介绍最後一项 OpenStack 元件,Cinder。Ci...

DAY29-ASP.NET网页切换导向及状态管理-趴水

ASP.NET网页切换导向及状态管理-趴水 今天来做做看 在网页输入资料後 按下按钮 可以将资料导向...

【Day 15】Function 函式

前言 函式用於结构化程序,将需要重复用到的功能独立出来,透过函式的呼叫,传入资料与回传处理後的资料。...

2 游戏规则

所以到底是要做怎样 昨天列出了一些还在考虑的点,做了一些粗暴的决定: Q: 要让这个游戏可以用桌游的...

IOS、Python自学心得30天 Day-11 模组训练改善-3

前言: 经过一个晚上的找资料,模组终於能继续训练,但目前还没有强制停止储存模型的方法,所以之後会再改...