JavaScriptでは、イベントのバブリングを利用し、親要素にイベント処理を委譲することができます。
イベント委譲の利点は、イベントを発生させる要素ごとにイベントを設定しなくて済み、コードの見通しがよくなることです。
sample
サンプルとして、[start], [stop], [reset] ボタン3つで操作する、10分の1秒単位で計測するストップウォッチを作成しました。
ポイントとしては、
- 各ボタンの親要素である、id="controller" のdiv要素にのみ、onclick イベントリスナを設定している。(22行目)
- div要素内でonclickイベントが発生したら、発生元のid属性をチェックし、各ボタンごとの処理を呼び出している。(30行目)
ことです。
サンプルコード
<body>
<div id="controller">
<input type="button" value="start" id="start"/>
<input type="button" value="stop" id="stop"/>
<input type="button" value="reset" id="reset"/>
</div>
<div id="display" ></div>
<script type="text/javascript">
(function setStopWatch(){
var stopWatch = {
controller : document.getElementById("controller"),
disp : document.getElementById("display"),
intervalId : undefined,
state : "off",
init : function(){
this.disp.innerHTML = 0;
var that = this;
//各ボタンの親要素にだけevent を設定する
this.controller.onclick = function(e){
var evt = e || window.event;
var src = evt.target || evt.srcElement;
//これ以上はバブリングさせない
evt.stopPropagation ? evt.stopPropagation() : evt.cancelBubble = true;
//クリックされたボタンの処理を呼び出す
that[src.id]();
};
},
//以下各ボタンの処理
start : function(){
if (this.state === "on") { //既に実行中の場合は処理しない
return
};
var that = this;
that.intervalId = setInterval(function(){
var c = parseFloat(that.disp.innerHTML);
that.disp.innerHTML = (c += 0.1).toFixed(1); //小数第1位までを表示
}, 100);
this.state = "on";
},
stop: function(){
if (this.state === 'on'){
clearInterval(this.intervalId);
}
this.state = "off";
},
reset: function(){
if (this.state === 'on'){
clearInterval(this.intervalId);
}
this.disp.innerHTML = 0;
this.state = "off";
}
}
stopWatch.init();
})();
</script>
</body>
jQueryでイベント委譲する場合
jQuery では、
.delegate() メソッドが用意されているので、より簡単にイベント委譲を実装できます。
$("div#controller").delegate("input#start", "click", handler);
まとめ
- 同一要素内でたくさんのイベントリスナをセットする場合は、イベント委譲でまとめられないか検討する!
参考文献
JavaScript パターン p196 - p197
JavaScriptパターン ―優れたアプリケーションのための作法
0 件のコメント:
コメントを投稿