使用Update进行嵌套选择

时间:2018-06-12 13:34:18

标签: d3.js

我已经构建了我认为nested selection update pattern的最新解决方案。

但是,每次单击更新时,我总是得到外部选择,但不总是内部(嵌套)选择。日志到控制台显示正确形成的数组数组。

这是v5中嵌套选择的正确设置吗? Here's a codepen



<!doctype html>
<html>

<head>
  <meta charset="UTF-8">
  <title>#</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://d3js.org/d3.v5.min.js"></script>
  <style type="text/css">
    .outer {
      border: 1px solid black;
      background-color: grey;
      width: 100%;
      height: 100px;
      position: relative;
      display: flex;
    }
    
    .inner {
      display: flex;
      justify-content: flex-start;
      border: 1px solid blue;
      background-color: cyan;
      width: 50px;
      height: 50px;
      position: relative;
    }
  </style>

</head>

<body>
  <button id='update'>update</button>
  <div id="anchor"></div>
  <script>
    const updateButton = document.getElementById('update');
    const anchor = d3.select('#anchor');

    updateButton.addEventListener('click', function() {
      update(
        Array.from({
          length: Math.ceil(Math.random() * 5)
        }, function() {
          return Array.from({
            length: Math.ceil(Math.random() * 5)
          }, function() {
            return Math.ceil(Math.random() * 5);
          });
        })
      );
    });


    function update(data) {

      const outer = anchor.selectAll('.outer').data(data);

      outer.exit().remove();

      outer.enter()
        .append('div')
        .merge(outer)
        .attr("class", "outer");

      const inner = outer.selectAll('.inner').data(function(d) {
        return d;
      });

      inner.exit().remove();

      inner.enter()
        .append('div')
        .merge(inner)
        .attr("class", "inner")
        .text(function(d) {
          return d;
        });
    }
  </script>
</body>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

在这种情况下你必须重新分配更新选择,因此它的引用与输入选择合并(这里我改变了const {{1}为了重新分配选择):

let

否则//here is the update selection: let outer = anchor.selectAll('.outer').data(data); //here is the enter selection: const outerEnter = outer.enter() .append('div') .attr("class", "outer"); //reassigning here: outer = outerEnter.merge(outer); 将只是更新选择,即使您在输入选择中链接了other方法也是如此。如果您安装merge,则可以清楚地看到这一点。

以下是您更改的代码:

&#13;
&#13;
outer.size()
&#13;
const updateButton = document.getElementById('update');
const anchor = d3.select('#anchor');

updateButton.addEventListener('click', function() {
  update(
    Array.from({
      length: Math.ceil(Math.random() * 5)
    }, function() {
      return Array.from({
        length: Math.ceil(Math.random() * 5)
      }, function() {
        return Math.ceil(Math.random() * 5);
      });
    })
  );
});


function update(data) {
  let outer = anchor.selectAll('.outer').data(data);

  outer.exit().remove();

  const outerEnter = outer.enter()
    .append('div')
    .attr("class", "outer");

  outer = outerEnter.merge(outer);

  const inner = outer.selectAll('.inner').data(function(d) {
    return d;
  });

  inner.exit().remove();

  inner.enter()
    .append('div')
    .attr("class", "inner")
    .merge(inner)
    .text(function(d) {
      return d;
    });
}
&#13;
	.outer {
		border: 1px solid black;
		background-color: grey;
		width: 100%;
		height: 100px;
		position: relative;
		display: flex;
	}
	.inner {
		display: flex;
		justify-content: flex-start;
		border: 1px solid blue;
		background-color: cyan;
		width: 50px;
		height: 50px;
		position: relative;
	}
&#13;
&#13;
&#13;