【问题标题】:D3.js: Is this good practise for data-DOM-binding?D3.js:这是数据 DOM 绑定的好习惯吗?
【发布时间】:2023-03-22 13:13:01
【问题描述】:

我正在尝试掌握 D3 的基础知识。我知道正确绑定很重要。

于是我做了一个简单的网页,包含更新、进入和退出操作。每次数据更改(修改、添加、删除)时,我都会调用一个函数,其中数据在更新、进入和退出方式中绑定到 svg-objects。

我想知道我的方法是不是一个好方法?

<html>
<head>

<style>
  .drawarea { border-style: solid; }
</style>

<script src="https://d3js.org/d3.v4.min.js"></script>

<script>
var data, drawArea;

function init(){
  data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];

  drawArea = d3.select("#drawareadiv").append("svg:svg")
    .attr("class", "drawarea")
    .attr("width", 500)
    .attr("height", 250);

  draw();
}

function draw(){
  var domRects = drawArea.selectAll("rect");

  // update
  domRects
    .data(data)
    .attr("x", function(d) { return d.px; })
    .attr("y", function(d) { return d.py; })
    .attr("width", function(d) { return d.s; })
    .attr("height", function(d) { return d.s; });

  // enter
  domRects
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function(d) { return d.px; })
    .attr("y", function(d) { return d.py; })
    .attr("width", function(d) { return d.s; })
    .attr("height", function(d) { return d.s; });

   // exit
   domRects
     .data(data)
     .exit()
     .remove();
}

function updateDataAndBinding(){
  for(i=0; i<data.length; i++)
    data[i].px += 10;
  draw();
}

function enterDataAndBinding(){
  var px = 25;
  var py = 25 * (data.length+1);
  var s = Math.floor(data.length/2)*5+5;
  data.push({"px" : px, "py" : py, "s" : s});
  draw();
}

function exitDataAndBinding(){
  data.splice(data.length-1, 1);
  draw();
}

</script>

</head>

<body onload="init()">
<div id="drawareadiv"></div>
<button onclick="updateDataAndBinding()">updateDataAndBinding</button>
<button onclick="enterDataAndBinding()">enterDataAndBinding</button>
<button onclick="exitDataAndBinding()">exitDataAndBinding</button>
</body>

</html>

【问题讨论】:

    标签: d3.js idioms


    【解决方案1】:

    我建议两件事:

    1. 不要一次又一次地绑定数据。只做一次:

      var domRects = drawArea.selectAll("rect").data(data);
      
    2. 由于这是 D3 v4.x,请使用 merge 一起处理“输入”和“更新”选择:

      // enter + update
      domRects.enter()
          .append("svg:rect")
          .attr("x", function(d) { return d.px; })
          .attr("y", function(d) { return d.py; })
          .attr("width", function(d) { return d.s; })
          .attr("height", function(d) { return d.s; })
          .merge(domRects)
          .attr("x", function(d) { return d.px; })
          .attr("y", function(d) { return d.py; })
          .attr("width", function(d) { return d.s; })
          .attr("height", function(d) { return d.s; });
      

    这里是演示(点击“运行代码sn-p”):

    <style>
      .drawarea { border-style: solid; }
    </style>
    
    <script src="https://d3js.org/d3.v4.min.js"></script>
    
    <script>
    var data, drawArea;
    
    function init(){
      data = [{"px" : 25, "py" : 25, "s" : 5}, {"px" : 25, "py" : 50, "s" : 5}, {"px" : 25, "py" : 75, "s" : 10} ];
    
      drawArea = d3.select("#drawareadiv").append("svg:svg")
        .attr("class", "drawarea")
        .attr("width", 500)
        .attr("height", 200);
    
      draw();
    }
    
    function draw(){
      var domRects = drawArea.selectAll("rect").data(data);
    
      // enter
      domRects.enter()
        .append("svg:rect")
        .attr("x", function(d) { return d.px; })
        .attr("y", function(d) { return d.py; })
        .attr("width", function(d) { return d.s; })
        .attr("height", function(d) { return d.s; })
    		.merge(domRects)
    		.attr("x", function(d) { return d.px; })
        .attr("y", function(d) { return d.py; })
        .attr("width", function(d) { return d.s; })
        .attr("height", function(d) { return d.s; });
    
       // exit
       domRects.exit()
         .remove();
    }
    
    function updateDataAndBinding(){
      for(i=0; i<data.length; i++)
        data[i].px += 10;
      draw();
    }
    
    function enterDataAndBinding(){
      var px = 25;
      var py = 25 * (data.length+1);
      var s = Math.floor(data.length/2)*5+5;
      data.push({"px" : px, "py" : py, "s" : s});
      draw();
    }
    
    function exitDataAndBinding(){
      data.splice(data.length-1, 1);
      draw();
    }
    
    </script>
    
    </head>
    
    <body onload="init()">
    <div id="drawareadiv"></div>
    <button onclick="updateDataAndBinding()">updateDataAndBinding</button>
    <button onclick="enterDataAndBinding()">enterDataAndBinding</button>
    <button onclick="exitDataAndBinding()">exitDataAndBinding</button>
    </body>

    除此之外,您的方法似乎是一种很好(和标准)的方法。

    【讨论】:

      猜你喜欢
      • 2016-06-27
      • 2021-03-15
      • 2021-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-11
      • 2012-09-12
      相关资源
      最近更新 更多