D3:为什么 'get' 操作会破坏价值

D3: Why does a 'get' action spoil the value

这是一个奇怪的情况,没有参数的 D3 的 datum() 函数是一个 get 函数,破坏了绑定到元素的值。

JS斌link:
https://jsbin.com/jokarapovi/edit?html,js,console

HTML:

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
</head>
<body>
  <svg id="s">
    <g id="g"></g>
  </svg>
</body>
</html>

JavaScript:

var log = console.log;

d3.select("#s").datum(1);
d3.select("#g").datum(2);

var s = d3.select("#s");
var g = d3.select("#g");
log("svg datum:",s.datum());
log("g datum:",g.datum());

// This line is a 'get' but it spoils the value
var temp = s.select("#g").datum();

// Wrong value:
log("g datum:",d3.select("#g").datum());

这是损坏的输出:

"svg datum:" 1
"g datum:" 2
"g datum:" 1

为什么 get 函数(D3 datum() 没有参数)破坏绑定到元素的值?

您看到的行为是 selection.select() 的结果,我们可以从您的 get 行中删除 .datum(),结果是相同的:

var log = console.log;

d3.select("#s").datum(1);
d3.select("#g").datum(2);

var s = d3.select("#s");
var g = d3.select("#g");
log("svg datum:",s.datum());
log("g datum:",g.datum());

// This get is a 'get' but it spoils the value
var temp = s.select("#g")//.datum();

// Wrong value:
log("g datum:",d3.select("#g").datum());
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
</head>
<body>
  <svg id="s">
    <g id="g"></g>
  </svg>
</body>
</html>

这是因为selection.select将绑定到selection的数据绑定到选定的子元素(覆盖之前的数据):“如果当前元素有关联数据,则此数据传播到相应的选定的元素。” (docs)

这在 D3 中通常是理想的,一对一的父子关系通常具有相同的父子数据。

如果您不想将父级的数据传递给子级,最简单的方法是存储对子级的引用或使用允许直接选择它的标识符,从而避免该问题:

var log = console.log;

d3.select("#s").datum(1);
d3.select("#g").datum(2);

var s = d3.select("#s");
var g = d3.select("#g");
log("svg datum:",s.datum());
log("g datum:",g.datum());

// This get is a 'get' but it spoils the value
var temp = d3.select("#g").datum();

// Wrong value:
log("g datum:",d3.select("#g").datum());
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
</head>
<body>
  <svg id="s">
    <g id="g"></g>
  </svg>
</body>
</html>