【问题标题】:Is exit selection necessary in D3?D3中是否需要退出选择?
【发布时间】:2021-03-01 15:57:11
【问题描述】:

我在 D3 中使用数据连接创建了这个简单的示例。它的工作原理:当用户点击+1 时,green 被添加到列表中,当点击-1 时,列表中的最后一个颜色被删除。

代码如下:

const colors = ["white", "yellow", "red", "brown", "orange"];
    const root = d3.select("#root");
    const addColor = d3.select("#add-color");
    addColor.on("click", (d) => {
      colors.push("green");
      update();
    });
    const removeColor = d3.select("#remove-color");
    removeColor.on("click", (d) => {
      colors.pop();
      update();
    });
    const ul = root.append("ul");
    ul.selectAll("li")
      .data(colors)
      .join(
        (enter) => enter.append("li").text((d) => d),
        (update) => update,
        (exit) => exit.remove()
      );
      
    function update(){
      ul.selectAll("li")
      .data(colors)
      .join(
        (enter) => enter.append("li").text((d) => d),
        (update) => update,
        (exit) => exit.remove()
      );
    }
#buttons-container {
      display: flex;
      margin-bottom: 30px;
    }
    #buttons-container div {
      min-width: 30px;
      text-align: center;
      cursor: pointer;
      border: 1px solid black;
      margin-right: 50px;
    }
<!DOCTYPE html>
    <meta charset="utf-8" />
    <html>
      <body>
        <div id="root">
          <div id="buttons-container">
            <div id="add-color">+1</div>
            <div id="remove-color">-1</div>
          </div>
        </root>
        <script
          type="text/javascript"
          src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"
        ></script>
        <script type="text/javascript" src="./index.js"></script>
        <script type="text/css" src="./styles.css"></script>
      </body>
    </html>

然后我评论了退出动作:

function update() {
  ul.selectAll("li")
    .data(flavors, (d) => d)
    .join(
      (enter) =>
        enter
          .append("li")
          .text((d) => d)
          .style("color", "green"),
      (update) => update.style("color", "steelblue"),
      //(exit) => exit.style("color", "red").remove()
    );
}

它以同样的方式工作。我错过了什么? exit有必要吗?

【问题讨论】:

    标签: javascript html d3.js


    【解决方案1】:

    默认情况下,.join 调用 selection.remove() 以获取现有选择,而无需显式传递函数。代码是等价的。

    【讨论】:

      【解决方案2】:

      join 方法是最近添加到 d3 的,它管理完整的更新模式(进入、更新、退出)。

      可以以最简单的方式使用,无需指定模式的任何部分,例如,

       ul.selectAll("li")
          .data(flavors, (d) => d)
          .join("li")
                .text((d) => d)
                .style("color", "green");
      

      简而言之,上面的代码将处理附加部分,将更新现有元素并删除任何不需要的元素。相当于:

      var list = ul.selectAll("li")
          .data(flavors, (d) => d);
      
      list.enter()
          .append("li")
          .merge("list")
          .text((d) => d)
          .style("color", "green");
      
      list.exit().remove();
      

      如果我们想为模式的一部分添加特定的操作,我们可以指定每个操作。

      在你的情况下,如果你只想区分输入和更新的颜色,那么你不需要指定退出部分。

      【讨论】:

        【解决方案3】:

        只是为了添加到已经存在的答案,您的问题标题有点误导。让我们看看你的标题和一些变体:

        • “在 D3 中是否需要选择退出?”

          不,不是。您可以完美地拥有没有退出选择的 D3 代码。实际上,您甚至可以在不调用selection.remove() 的情况下进行退出选择,也就是说,您可以对退出选择执行其他操作,而不仅仅是删除元素(例如,设置不同的颜色)。这给我们带来了另一个问题:

        • “[the] exit selection 是 'elements to be removed' 的同义词吗?”

          不,不是。

        • “在动态数据可视化中是否需要退出选择?”

          通常是的,但是这又不是必要的。所以正确的答案是

        • “在selection.join() 中是否需要选择退出?”

          我相信 this 是您要问的问题。好吧,正如其他答案所指出的那样,退出选择已经存在。这里有一个简短的解释:

        如果你看看source code,它很小,你会看到:

        export default function(onenter, onupdate, onexit) {
          var enter = this.enter(), update = this, exit = this.exit();
          enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
          if (onupdate != null) update = onupdate(update);
          if (onexit == null) exit.remove(); else onexit(exit);
          return enter && update ? enter.merge(update).order() : update;
        }
        

        因此,正如您在这一行中看到的那样......

        if (onexit == null) exit.remove(); else onexit(exit);
        

        ...如果你显式设置了一个退出函数(这里的参数名为onexit),代码将调用它,否则它会简单地执行exit.remove(),实际上是this.exit.remove(),其中this是选择。

        最后有趣的是,作为一种方便的方法,selection.join() 假定用户想要删除退出选择中的元素。但是,正如我已经解释的那样,这不是必需的。

        【讨论】:

          猜你喜欢
          • 2012-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-02
          • 1970-01-01
          • 1970-01-01
          • 2021-03-26
          • 1970-01-01
          相关资源
          最近更新 更多