d3:如何在enter()上添加嵌套元素?我的元素会被追加,但后续的选择却看不到它们

时间:2017-06-19 18:33:33

标签: javascript d3.js

示例小提琴:https://jsfiddle.net/tomaskafka/w1acm8ox/

这是我的更新循环:

var output = d3.select('#output')
    .selectAll('p')
    .data(data)
    ;

output
    .enter()
        .append('p')
        .call(function(parent) {
            parent.append('a')
        });
        ;

output
    .exit()
        .remove()
    ;

// PROBLEM: at this point, element addded right now isn't selected, and so it's attr and text isn't set.
output
    .select('a')
        .attr('href', function(d) { return 'http://www.google.com?q=' + d; })
        .text(function(d) { return d; })
    ;
你可以帮忙吗?我理解由于一些优化,d3不会立即更新DOM,那么添加嵌套元素并在更新时设置它的属性的正确方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

您没有正确使用更新,输入,退出模式。

您的输入选择已附加:

output
    .enter()
        .append('p')
        .call(function(parent) {
            parent.append('a')
        });

但是,你在这里遇到了问题:

output
    .select('a')
        .attr('href', function(d) { return 'http://www.google.com?q=' + d; })
        .text(function(d) { return d; })
    ;

仅更新创建选区时存在的元素。因此,新创建的元素(输入选择的一部分)不受影响。这是更新选择,与输入选择互斥 - 这与v3不同,需要使用合并方法将更新选择与输入选择组合。

这就是你必须使用超时的原因 - 第一次运行更新功能时会附加功能,第二次更新功能。

而是尝试:

output
  .enter()
    .append('p')
    .call(function(parent) { parent.append('a') })
  .merge(output).select('a')
    .attr('href', function(d) { return 'http://www.google.com?q=' + d; })
    .text(function(d) { return d; });

输入选择将导致p被追加,然后我们合并输入和更新选择,以便使用特定文本更新所有元素。现在您可以删除超时功能,移动滑块时,更新应该正确显示。

这是更新的片段:



var items = [1,2,3,4,5,6,7,8,9,10,11,12,13]

var slider = d3.select('#slider')
	.attr('min', 0)
	.attr('max', items.length)
	.attr('value', items.length - 1)
	.attr('step', 1)
	.attr('disabled', null) // enable
	;

function update(data) {
	var output = d3.select('#output')
		.selectAll('p')
		.data(data)
		;

	output
		.enter()
			.append('p')
			.call(function(parent) {
				parent.append('a')
			})
      .merge(output).select('a')
			.attr('href', function(d) { return 'http://www.google.com?q=' + d; })
			.text(function(d) { return d; });
			;

	output
		.exit()
			.remove()
		;
}
update(['a', 'b', 'c']);

slider.on('input', function() {
	var val = +this.value;
	var newData = items.slice(0, val);

	update(newData);
});

body {
		font-family: sans-serif;
	}

	p {
		outline: 1px red solid;
	}
	a {
		display: inline-block;
		outline: 1px blue solid;
		min-width: 1em;
		min-height: 1em;
	}

	.small {
		font-size: 66%;
	}

	#slider {
		width: 100%;
	}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>
<div id="wrap">
	<input type="range" id="slider" disabled="disabled" />
	<div class="small" id="output">static content</div>
</div>
&#13;
&#13;
&#13;