Javascript d3 v5树布局数据更新重新创建树,而不是更新节点

Javascript d3 v5树布局数据更新重新创建树,而不是更新节点,javascript,d3.js,data-visualization,d3tree,Javascript,D3.js,Data Visualization,D3tree,我正在开发一个应用程序,在这个应用程序中,我希望以树状结构显示我的分层数据。这个数据不断更新,我想根据新收到的数据更新树。通过将新数据与新数据合并,我已经使用D3V3成功地实现了它 我现在想升级到D3V5。到目前为止,我已经能够创建树,但我无法处理数据更新。每当我获得新数据时,就会重新创建整个树,我看到每次都会为每个节点触发enter()和exit()事件。 注意:如果展开折叠不起作用,请忽略,我仍在处理此问题 我提取了下面创建的代码工作片段来描述我的问题。我不希望每次收到新数据时都重新创建树,

我正在开发一个应用程序,在这个应用程序中,我希望以树状结构显示我的分层数据。这个数据不断更新,我想根据新收到的数据更新树。通过将新数据与新数据合并,我已经使用D3V3成功地实现了它

我现在想升级到D3V5。到目前为止,我已经能够创建树,但我无法处理数据更新。每当我获得新数据时,就会重新创建整个树,我看到每次都会为每个节点触发enter()和exit()事件。 注意:如果展开折叠不起作用,请忽略,我仍在处理此问题

我提取了下面创建的代码工作片段来描述我的问题。我不希望每次收到新数据时都重新创建树,我只希望在数据发生任何更改时更新现有节点,否则节点保持原样

我错在哪里?你能推荐一个吗

//代码在这里
//查找元素
var保证金={
前20名,
右:90,,
底数:30,
左:90
},
宽度=660-margin.left-margin.right,
高度=300-margin.top-margin.bottom;
i=0,
持续时间=750,
半径=10;
var节点={};
var root={};
var-links={};
var节点=[];
var-links=[];
//句柄单击并添加类
$(“#btnLoadData”)。单击(函数(){
刷新数据();
});
函数refreshData(){
风险值数据={
“名称”:“中央”,
“connectionState”:Math.random()>0.5?“已连接”:“已断开”,
“父项”:空,
“环境状况”:{
“cpu”:45.575,
“mem”:55.8,
“磁盘”:85.5
},
“子状态”:“,
“儿童”:[{
“名称”:“UK-STORE1”,
“connectionState”:Math.random()>0.5?“已连接”:“已断开”,
“子状态”:“,
“环境状况”:{
“cpu”:45.650000000000006,
“mem”:55.8,
“磁盘”:85.5
},
“儿童”:[{
“名称”:“UK-TILL1”,
“connectionState”:Math.random()>0.5?“已连接”:“已断开”,
“子状态”:空,
“环境状况”:{
“cpu”:46.025000000006,
“mem”:55.8,
“磁盘”:85.5,
},
“children”:空,
“状态变更日期”:“2020-02-08 20:59:35.226769”
},
{
“名称”:“UK-TILL2”,
“connectionState”:Math.random()>0.5?“已连接”:“已断开”,
“子状态”:空,
“环境状况”:{
“cpu”:45.775000000000006,
“mem”:56.1,
“磁盘”:85.5
},
“children”:空,
“状态变更日期”:“2020-02-08 20:59:35.226769”
}
],
“状态变更日期”:“2020-02-08 20:59:35.226769”
}]
}
buildRoot(数据);
}
函数buildRoot(newSource){
root=d3.层次结构(newSource,函数(d){
返回d.儿童;
});
根x=0;
根。y=宽度/2;
root.x0=0;
root.y0=宽度/2;
updateTree(根目录)
}
var svg=d3.选择(“树”).追加(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部);
var mainG=svg.append(“g”)
.attr(“转换”,
“翻译(“+margin.left+”,“+margin.top+”);
var treeLayout=d3.tree()
.尺寸([宽度、高度]);
//.nodeSize([100,50]);
//折叠节点及其所有子节点
功能崩溃(d){
如果(d.儿童){
d、 _children=d.children
d、 _儿童。forEach(崩溃)
d、 children=null
}
}
函数updateTree(源代码){
var treeData=treeLayout(根);
var newNodes=treeData.subjects();
_.merge(节点、新节点)
var newlinks=treeData.subjects().slice(1);
_.merge(链接、新建链接)
nodes.forEach(函数(d){
dy=d.深度*180
});
//链接
var linkpath=mainG.selectAll(“.link”)
.数据(链接、功能(d){
返回d.id;
});
var linkEnter=linkpath.enter().append(“路径”)
.attr(“类”、“链接”)
.attr('d',函数(d){
变量o={
x:source.x0,
y:source.y0
}
返回对角线(o,o);
});
var linkUpdate=linkEnter.merge(链接路径);
linkUpdate.transition()
.持续时间(持续时间)
.attr('d',函数(d){
返回对角线(d,d.父项)
});
var linkExit=linkpath.exit()
.transition()
.持续时间(持续时间)
.attr('d',函数(d){
变量o={
y:source.y0,
x:source.x0
}
返回对角线(o,o)
})
.remove();
//节点
var node=mainG.selectAll('g.node')
.数据(节点、功能(d){
返回d.id | |(d.id=++i);
});
//更新节点
var nodeEnter=node.enter().append('g')
.attr('类','节点')
.attr(“转换”,函数(d){
返回“translate”(“+source.x0+”,“+source.y0+”);
})
.on('点击',点击);
//附加圆
nodeEnter.append(“圆”)
.attr(“类”、“圈”)
.attr(“r”,半径);
//附加圆
nodeEnter.append(“文本”)
.attr(“类”、“节点名”)
.文本(功能(d){
返回d.data.name;
});
//更新
var nodeUpdate=nodenter.merge(节点);
//转换到节点的正确位置
nodeUpdate.transition()
.持续时间(持续时间)
.attr(“转换”,函数(d){
返回“translate”(“+d.x+”,“+d.y+”);
});
节点更新。选择(“圆圈”)
.attr(“类”,函数(d){
console.log(d.data.connectionState);
返回d.data.connectionState==“已连接”?“已连接的圆”:“已断开的圆”
})
//删除任何现有节点
var nodeExit=node.exit().transition()
.持续时间(持续时间)
.attr(“转换”,函数(d){
返回“translate”(“+source.y+”,“+source.x+”);
})
.remove();
//退出时,将节点圆的大小减小为0
nodeExit.select('circle')
.attr('r',1e-6);
//退出时减少文本标签的不透明度
nodeExit.select('text')
.样式(“填充不透明度”,1e-6);
函数对角线(s,d){
path=`M${s.x}${s.y}
C