2017-04-26 79 views
2

我正在嘗試向圖中的酒吧添加事件。我嘗試了這個function波紋管,但是使用這個功能它並不重要我點擊的是什麼,它總是會返回array中的最後一個keyD3 - 將事件添加到酒吧

我的猜測是這與異步有關,因爲它返回最後的key值。

for (var key in data) { 
    bar = bars.append('rect') 
    .attr('class', 'bar') 
    .attr('x', (dimensions.width/data.length) * currentId + 41) 
    .attr('y', 100 - data[key] + 10).attr('height', data[key]) 
    .attr('width', dimensions.width/data.length) 
    .attr('fill', '#4682B4') 
    .on('click', (bar = key) => { 
     console.log(key) //Always returns the same key 
    }); 
    currentId++; 
} 

我也試圖複製該數組包含的關鍵之一,並作出if語句是這樣的:

console.log(key === 1 ? true : false); 

這將返回truefalse,正是因爲它應該。我認爲這與async有關的另一個原因。

我的根本問題是; 我怎樣才能讓這條上的點擊事件,這將返回正確的key

回答

2

別的之前:這是在D3中添加事件的慣用方式。作爲一般規則,當你編寫D3代碼時,你通常不需要任何類型的循環。當然,我們有時候會使用循環,但是在非常特殊的情況下並且要解決非常具體的問題。因此,在D3代碼中找到的循環中有98.57%是不必要的(來源:FakeData Inc.),可以是for...infor...of或簡單的for循環。

這就是說,讓我們看看這裏發生了什麼。

你真正的問題與D3或異步代碼無關。其實,你的問題可以用這個優秀的答案來解釋:JavaScript closure inside loops – simple practical example(儘管我會避免把它作爲一個副本來關閉)。

在閱讀上面鏈接中的答案之後,我們來看兩個演示。

第一個,使用var。請點擊圓圈:

var data = [{ 
 
    name: "foo", 
 
    value: 1 
 
}, { 
 
    name: "bar", 
 
    value: 2 
 
}, { 
 
    name: "baz", 
 
    value: 3 
 
}]; 
 

 
var svg = d3.select("svg"); 
 

 
for (var key in data) { 
 
    var foo = key;//look at the var here 
 
    circle = svg.append("circle") 
 
    .attr("cy", 50) 
 
    .attr("fill", "teal") 
 
    .attr("cx", d=> 20 + key*50) 
 
    .attr("r", 15) 
 
    .on('click',() => { 
 
     console.log(foo) 
 
    }); 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<svg></svg>

現在一個又一個,使用let,請點擊圈,並比較結果:

var data = [{ 
 
    name: "foo", 
 
    value: 1 
 
}, { 
 
    name: "bar", 
 
    value: 2 
 
}, { 
 
    name: "baz", 
 
    value: 3 
 
}]; 
 

 
var svg = d3.select("svg"); 
 

 
for (var key in data) { 
 
    let foo = key;//look at the let here 
 
    circle = svg.append("circle") 
 
    .attr("cy", 50) 
 
    .attr("fill", "teal") 
 
    .attr("cx", d=> 20 + key*50) 
 
    .attr("r", 15) 
 
    .on('click',() => { 
 
     console.log(foo) 
 
    }); 
 
}
<script src="https://d3js.org/d3.v4.min.js"></script> 
 
<svg></svg>

+0

難道你也許提供一個鏈接到聲明的來源「作爲一般規則,當你寫一個D3鱈魚e,你通常不需要任何形式的循環。「? – FlorisdG

+0

該聲明的來源是我的專業經驗和任何經驗豐富的D3編碼器的經驗。你可以在任何關於D3的教程,書籍或文檔中看到它。這個由D3創建者Mike Bostock編寫的頁面是一個很好的起點:https://bost.ocks.org/mike/join/ –

+0

正如他所說,*「...在你開始一個** for循環之前* *並蠻力,從D3的一個例子考慮這個神祕的序列......「* –