Javascript 有条件地附加或删除子元素

Javascript 有条件地附加或删除子元素,javascript,d3.js,Javascript,D3.js,我有一个复杂的图形,上面有带文本的线条;但是,存在性能问题(SVG变得有点太忙)。我希望能够切换文本是否呈现。下面是一个简化的示例,目的是根据复选框的值呈现或不呈现文本: const data=[“foo”、“bar”、“baz”]; const svg=d3.select('#graph'); const g=svg.append('g'); 函数渲染(数据、显示文本){ 常量lineG=g.selectAll('g') .数据(数据) .join('g')) lineG.append('p

我有一个复杂的图形,上面有带文本的线条;但是,存在性能问题(SVG变得有点太忙)。我希望能够切换文本是否呈现。下面是一个简化的示例,目的是根据复选框的值呈现或不呈现文本:

const data=[“foo”、“bar”、“baz”];
const svg=d3.select('#graph');
const g=svg.append('g');
函数渲染(数据、显示文本){
常量lineG=g.selectAll('g')
.数据(数据)
.join('g'))
lineG.append('path')
.attr('d',(d,i)=>`M10,${(i+1)*30}l100,0`)
.attr('id',(d,i)=>`line-${i}`)
.attr(“笔划”、“黑色”);
if(showText){//方法错误
lineG.append('text')
.attr('dy',-2)
.append('textPath')
.attr('href',(d,i)=>`line-${i}`)
.text(d=>d);
}
}
呈现(数据,真实);
d3.选择(“#切换文本”)
.on('单击',evt=>{
const checked=evt.target.checked;
渲染(数据,选中);
});



显示文本
请注意,无论何时在非空选择上使用
.append
,您都在添加元素。因此,在渲染函数中,每次调用时都要添加元素

对于这个答案,我只运行了一次
render
,但是如果您想运行多次,您应该阅读关于使用常规更新模式的内容

与多次调用
render
不同,您可以只更新文本,使用
append
remove
添加和删除文本。我在下面举了一个例子:

const data=[“foo”、“bar”、“baz”];
const svg=d3.select('#graph');
const g=svg.append('g');
var-lineG;
函数渲染(数据){
lineG=g.selectAll('g')
.数据(数据)
.加入(“g”);
lineG.append('path')
.attr('d',(d,i)=>`M10,${(i+1)*30}l100,0`)
.attr('id',(d,i)=>`line-${i}`)
.attr(“笔划”、“黑色”);
}
var textShowed=null;
函数updateText(showText){
如果(文本显示===showText){
返回;
}
如果(显示文本){
线条
.append('文本')
.attr('dy',-2)
.append('textPath')
.attr('href',(d,i)=>`line-${i}`)
.text(d=>d);
}否则{
lineG.selectAll('text')。remove()
}
text显示=显示文本;
}
渲染(数据);
updateText(d3.select('#toggleText').property('checked'));
d3.选择(“#切换文本”)
.on('单击',evt=>{
const checked=evt.target.checked;
updateText(选中);
});



显示文本
在执行任何其他操作之前,不应像这样使用
lineG
:每次单击复选框时都会附加一个新路径

惯用的D3方法是使用输入/更新/退出选择。那应该是这样的

let text = lineG.selectAll(".myTextClass")
  .data((_, i) => showText ? [i] : []);

text.exit().remove();

const textEnter = text.enter()
  .append('text')
  .attr("class", "myTextClass")
  .attr('dy', -2);

textEnter.append('textPath')
  .attr('href', (d) => `#line-${d}`)
  .text(d => "foo");

text = textEnter.merge(text);
。。。处理
lineG
。D3非常详细,上面的代码片段甚至更详细,因为我们必须在
下添加

此外,这里我不使用索引(因为每个组只有一个文本),而是通过数据传递父级索引:

.data((_, i) => showText ? [i] : []);
以下是工作演示:

const data=[“foo”、“bar”、“baz”];
const svg=d3.select('#graph');
const g=svg.append('g');
函数渲染(数据、显示文本){
常量lineG=g.selectAll('g')
.数据(数据)
.join('g'))
lineG.append('path')
.attr('d',(d,i)=>`M10,${(i+1)*30}l100,0`)
.attr('id',(d,i)=>`line-${i}`)
.attr(“笔划”、“黑色”);
让text=lineG.selectAll(“.myTextClass”)
.数据((u,i)=>showText?[i]:[]);
text.exit().remove();
const textEnter=text.enter()
.append('文本')
.attr(“类”、“myTextClass”)
.attr('dy',-2);
textEnter.append('textPath')
.attr('href',(d)=>`line-${d}`)
.text(d=>“foo”);
text=textEnter.merge(文本);
}
呈现(数据,真实);
d3.选择(“#切换文本”)
.on('单击',evt=>{
const checked=evt.target.checked;
渲染(数据,选中);
});



显示文本
是的,这很有意义。我知道连接模式(我在上面的示例中使用了它)。我想知道自动添加/删除文本是否有意义,但是手动添加/删除文本实际上并不太简单。谢谢。哦,这看起来和我想象的很像,只是。。。工作:)事实上,我能再问一件事吗?正如你所看到的,我对d3的经验非常缺乏-你能修改你的代码以便显示原始数组而不是“foo”吗?我不知道如何实现“如果您需要用于其他目的的数据,请尝试另一种传递父级索引的方法,如局部变量或
选择。each()
”(嵌套
数据
打断我的大脑)@Amadan当然,请使用局部变量查看第二个代码段(我认为它们比
选择更容易理解。每个
)。如果嵌套数据打断了你的大脑……欢迎光临,你并不孤单。