Javascript ループ中にイベントリスナーを登録する最も簡単な方法

2月 28th, 2010 by admin Leave a reply »

今回はJavaScriptネタです。
こっち系はほとんど素人でぜんぜん得意ではありませんが、自分なりに考えてとってもナイスな方法を披露しちゃいます。

例えばこんな単純な処理
ちょっと文法があっているかどうかはわからんがこんなイメージ。

<ul id="hoge"></ul>

ここに動的に要素を足して、足された文字をクリックでその文字がアラートされる

 
var Kudamono = new Array("りんご","いちご","ばなな");
var ulElem = document.createElement('hoge');
for(var i = 0; i < Kudamono.length; i++){
  var liElem = document.createElement('li');
  liElem.innerHTML = Kudamono[i];
  liElem.onclick = function() { alert(Kudamono[i]);}
 
 ulElem.appendChild(liElem);
}

意図とすればリストタグが3つ追加され、
クリックするとアラートでその名前が表示されて欲しい。

だけど実際動かしてみると、全部最後の要素またはundefinedになる。
まったくもって意図した動作ではなくなる。

これは定義したときに動作がきまるのではなくて、動かしたときの変数が有効になるため。
クリックされたときは既にiが最後の値まで達しているのでそれを参照してしまうらしい。

そこでどんな回避策があるかといろいろ調べてみた。
http://d.hatena.ne.jp/hi_c_mayu/20090704/1246641410
http://labs.unoh.net/2006/05/post_11.html
http://cesare.seesaa.net/article/18007870.html

うーーん。。どれも素人の俺には使いにくい・・・。
そこでfunctionやパラメータを使うのではなく要素自身のなんらかの値を使ってしまうのがもっとも見やすくて簡単だと思った。

var Kudamono = new Array("りんご","いちご","ばなな");
var ulElem = document.createElement('hoge');
for(var i = 0; i < Kudamono.length; i++){
  var liElem = document.createElement('li');
  liElem.innerHTML = Kudamono[i];
  liElem.onclick = function() { alert(this.innerHTML);}
  ulElem.appendChild(liElem);
}

innerHTMLと値を明らかに変えたい場合は

  liElem.innerHTML = i + '番目の要素 ' +Kudamono[i]+'って美味しいよねー';
  liElem.title = Kudamono[i];
  liElem.onclick = function() { alert(this.title);}
  ulElem.appendChild(liElem);

ってな感じはどーだろうか。
自分ではナイスアイディアだと思うが(笑)

Advertisement

コメントを残す