いくつかのdivの#mydiv1
、#mydiv2
、#mydiv3
、...があり、クリックハンドラーをそれらに割り当てたい:
$(document).ready(function(){
for(var i = 0; i < 20; i++) {
$('#question' + i).click( function(){
alert('you clicked ' + i);
});
}
});
しかし、'you clicked 3'
をクリックしたときに#mydiv3
を表示する代わりに(他のすべてのクリックについて)'you clicked 20'
を取得します。私は何を間違えていますか?
JavaScriptで closures を作成するのはよくある間違いです。次のような何らかのコールバック関数が必要です。
function createCallback( i ){
return function(){
alert('you clicked' + i);
}
}
$(document).ready(function(){
for(var i = 0; i < 20; i++) {
$('#question' + i).click( createCallback( i ) );
}
});
2016年6月3日更新:この質問はまだ注目を集めており、ES6も人気を博しているため、最新のソリューションを提案します。 ES6を記述する場合、let
キーワードを使用できます。これにより、i
変数がグローバルではなくループに対してローカルになります。
for(let i = 0; i < 20; i++) {
$('#question' + i).click( function(){
alert('you clicked ' + i);
});
}
短くて理解しやすいです。
明確にするために、クリックイベントはループが終了するまで発生しないため、iは20です。
$(document).ready(function(){
for(var i = 0; i < 5; i++) {
var $li= $('<li>' + i +'</li>');
(function(i) {
$li.click( function(){
alert('you clicked ' + i);
});
}(i));
$('#ul').append($li);
}
});
on を使用して「クリック」ハンドラーをアタッチすると、次のようにデータを渡すためにイベントデータを使用できます。
for(var i = 0; i < 20; i++) {
$('#question' + i).on('click', {'idx': i}, function(e) {
alert('you clicked ' + e.data.idx);
});
}
//
// let's creat 20 buttons
//
for(var j = 0; j < 20; j++) {
$('body').append($('<button/>', {type: 'button', id: 'question' + j, text: 'Click Me ' + j}))
}
//
// Passing data to the handler
//
for(var i = 0; i < 20; i++) {
$('#question' + i).on('click', {'idx': i}, function(e) {
console.log('you clicked ' + e.data.idx);
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
クリックハンドラーを1回割り当てる(または、少なくとも多くの不要なクロージャーを作成しない)ことで取得できます。すべてのdivを1つのクラスmydivs
に入れてから:
$(document).ready(function(){
$('.mydivs').click(function(){
// Get the number starting from the ID's 6th character
// This assumes that the common prefix is "mydiv"
var i = Number(this.id.slice(5));
alert('you clicked ' + i);
});
});
slice
string method を使用して要素のIDを調べて番号を取得し、最初の文字を取り除きます。
注:使用することをお勧めします
$('#divcontainer').on('click', '.mydivs', function(){
の代わりに
$('.mydivs').click(function(){
一般的に、クリックハンドルを多数のアイテムに割り当てる場合、クリックがdomからバブルアップするため、クリックを解釈するコンテナー(高レベルdiv)が必要です。
<div id="bucket">
<span class="decorator-class" value="3">
...
</div>
<script>
$(document).ready(function(e){
$("#bucket").live('click', function(){
if(e.target).is('span'){
alert("elementid: " + $(e.target).val());
}
}
}
<script>