Javascript 为什么我的d3数据中的第一个元素没有被更新?

Javascript 为什么我的d3数据中的第一个元素没有被更新?,javascript,d3.js,Javascript,D3.js,因此,我目前正在使用此代码呈现元素列表,并(希望)指定活动元素,当单击其中一个元素时,活动元素可能会发生更改 让active\u experiment\u id=null; 函数集_实验(){ 常数u=d3。选择(“#实验”) .selectAll('li') .数据(对象.值(实验).排序((a,b)=>{ 常数a_时间=时刻(a[“已创建]), b_时间=时刻(b[‘创建’); if(a_time.isBefore(b_time)) 返回1; 否则,如果(a_时间。I在(b_时间)之后) 返

因此,我目前正在使用此代码呈现元素列表,并(希望)指定活动元素,当单击其中一个元素时,活动元素可能会发生更改

让active\u experiment\u id=null;
函数集_实验(){
常数u=d3。选择(“#实验”)
.selectAll('li')
.数据(对象.值(实验).排序((a,b)=>{
常数a_时间=时刻(a[“已创建]),
b_时间=时刻(b[‘创建’);
if(a_time.isBefore(b_time))
返回1;
否则,如果(a_时间。I在(b_时间)之后)
返回-1;
其他的
返回0;
}),(d)=>d);
常量输入=u.enter()
.append('li')
.classed('nav-item',true)
.classed('active',(d)=>d.active\u实验)
.on('click',d=>{
如果(d.实验id!==活动实验id)
设置活动实验(d.实验id);
})
.append('a')
.classed('nav-link',正确)
.classed('active',(d)=>d.active\u实验)
.append('p')
.text((d)=>{return d.name;});
u、 退出().remove();
}
函数集\活动\实验(实验id){
如果(实验id==null){
活动\u实验\u id=null;
设置_类(空);
设置工作流程(空);
设置任务(空);
设置所选任务(空,空);
返回;
}
如果(活动的实验id!==null)
实验[active\u experiment\u id]。active\u Experience=false;
活动实验id=实验id;
实验[active\u experiment\u id]。active\u Experience=true;
获取任务(实验id)
.然后(()=>{
设置_实验();
设置课程(实验id);
设置工作流(实验id);
设置任务(实验id);
设置所选任务(实验id,实验[实验id]。根任务id);
});
}
我目前在列表中有两个数据元素,我可以单击第二个,并获得要应用的
活动类。然而,我不能得到第一个被点击的。我尝试过调试,但在第一个任务中甚至没有调用enter函数(下面的实验id=2)。这些元素看起来像:

experiments = {1: {
  experiment_id: 1,
  name: "Experiment One",
  created: (before 2)
  ...
}, 2: {
  experiment_id: 2,
  name: "Experiment Two",
  created: (after 1),
  ...
}

我相信我已经解决了这个问题。因为我使用了
Object.values
,不知怎的,只有第二个实验保持了它的位置。之后,由于数据直接通过引用绑定(使用key
(d)=>d
),d3将一个元素与其自身进行比较,作为键测试。所以,无论您选择哪种键方法,d3都会将对象的键与自身进行比较,而不会注册对象已更新。因此,为了解决这个问题,我每次都创建一个数据的投影副本,并使用一个新的键方法来减少通过
enter
exit
的对象数量

函数集_实验(){
const key=d=>`${d.experiment\u id}${d.active\u experiment}`;
常量数据=对象。值(实验)。排序((a,b)=>{
常数a_时间=时刻(a[“已创建]),
b_时间=时刻(b[‘创建’);
if(a_time.isBefore(b_time))
返回1;
否则,如果(a_时间。I在(b_时间)之后)
返回-1;
其他的
返回0;
})
.map(d=>({
“实验id”:d.实验id,
“已创建”:d.已创建,
“姓名”:d.姓名,
“主动实验”:d.主动实验,
}));
常数u=d3。选择(“#实验”)
.selectAll('li')
.数据(数据、密钥);
常量输入=u.enter()
.append('li')
.classed('nav-item',true)
.classed('active',(d)=>{
num_输入++;
返回d.active_实验;
})
.on('click',d=>{
如果(d.实验id!==活动实验id){
设置活动实验(d.实验id);
}
})
.append('a')
.classed('nav-link',正确)
.classed('active',(d)=>{
返回d.active_实验;
})
.append('p')
.text((d)=>{return d.name;});
u、 退出().remove();
}

虽然它不是最有效的,因为我仍然必须复制所有数据,但复制的数据不会影响DOM。因为新的键方法删除了多余的添加和删除,所以只更新了值。

与您的问题无关,更多的是风格和品味问题:您的整个数据绑定可以显著简化为
.data(Object.values(experiments).sort((a,b)=>moment(b.created).diff(moment(a.created)),d=>d
moment.fn.diff()
将根据您对比较器函数感兴趣的符号进行计算。