是否有一种简单的方法可以扩展以下代码,以便在div.someclass
不存在时自动创建它?
d3.select("body").select("div.someclass").selectAll("p")
.data([ 1, 2, 3 ])
.enter()
.append("p")
.text(function (d, i) {
return "index: " + i + ", value: " + d;
});
我还处于学习D3JS的早期阶段。到目前为止,我对它的理解是“不是告诉D3如何做某事,而是告诉D3你想要什么”。所以我很惊讶地看到上面的代码需要在HTML中声明<div class="someclass"></div>
。
另一种方法是以编程方式插入div:
/** Append HTML placeholder programmatically **/
placeholder = d3.select("body").append("div").attr("class", "someclass");
/** Bind the data to the DOM **/
/** instead of telling D3 how to do something, tell D3 what you want: in the absence of <p>, this will return a virtual selection **/
placeholder.selectAll("p")
.data([ 1, 2, 3 ])
.enter()
.append("p")
.text(function (d, i) {
return "index: " + i + ", value: " + d;
});
有更短/更好的方式吗?
答案 0 :(得分:10)
如果我理解正确,你问的是如何追加div.someClass
IFF它不存在。这有一个D3模式,虽然它有点奇怪:
// create a selection for the container with a static 1-element array
var container = d3.select("body").selectAll("div.someclass")
.data([0]);
// now add it if it doesn't exist
container.enter().append('div').attr('class', 'someclass');
// now use it for the subselection
container.selectAll("p")
.data([1, 2, 3]);
// etc
这里的奇怪部分是.data([0])
- 0
是传统的,不是必需的;这可以是任何静态单元素数组。第一次调用它时,将创建一个新元素(除非先创建其他内容div.someclass
)。第二次,元素已经存在,因此没有.enter()
选择,并且不会再添加任何内容。
这是可重用组件中相当常见的模式,可以在更新时重复调用 - 有关示例,请参阅d3.svg.axis
code。
答案 1 :(得分:0)
你这样做的方式是正确的。通常,您以编程方式将类添加到以编程方式创建的节点。例如,您正在创建新的<p>
元素,以便在需要时可以在那里添加类:
placeholder.selectAll("p")
.data([ 1, 2, 3 ])
.enter()
.append("p")
.attr("class", "myclass") <-- add class here
.text(function (d, i) {
return "index: " + i + ", value: " + d;
});
对于您不使用D3管理生命周期的元素,您还需要以其他方式管理这些元素的属性。这可以在初始HTML中进行硬编码,或者您可以完全按照原样添加特殊处理。
或者,还有一个名为selection.classed的API,当且仅当它们不存在时才会添加或删除类。如果你的元素可能包含很多类,而你只想在列表中切换一个(而不是selection.attr("class", "myclass"
),这将会破坏整个属性,这可能很方便。