読者です 読者をやめる 読者になる 読者になる

Rails Webook

自社のECを開発している会社で働いています。Rails情報やサービスを成長させる方法を書いていきます

jQueryの疎結合なイベント処理

Javascript jQuery

f:id:nipe880324:20150311131822j:plain
Photo by Flickr: James Marvin Phelps' Photostream

jQueryを使ってイベント処理の登録と削除方法、登録できるイベントの一覧を説明します。
また、JavaScriptはイベントを通してHTMLと結びついているので、イベントハンドラのコーディングと修正に多くの時間を使います。
そのため、イベントハンドラとアプリケーションロジックを分離することで、疎結合にする考え方も説明します。

目次

  1. イベントハンドラの登録(on)
  2. イベントハンドラの削除(off)
  3. イベント一覧
  4. イベントハンドラとアプリケーションロジックを分離する

1. イベントハンドラの登録(on)

onメソッドを使うことでイベントハンドラを登録することができます。

// クリックのイベントハンドラを登録
$('#confirm').on('click', function() {
  return confirm('送信しますか?');
});

// 第二引数にセレクタを指定することで、現在の要素だけでなく、今後動的に追加された要素にもイベントハンドラを登録する
$('#confirm').on('click', 'input[type=submit]', function() {
  // ...
});

2. イベントハンドラの削除(off)

逆にoffメソッドを使うことで、登録してあるイベントハンドラを削除できます。

// すべてのイベントハンドラを削除
$('#confirm').off();

// clickのイベントハンドラを削除
$('#confirm').off('click');

// body要素ないのすべての送信ボタン(input[type=submit])からclickのイベントハンドラを削除
$('body').off('click', 'input[type=submit]');


3. イベント一覧

利用可能なイベントをまとめました。
名前 発生タイミング
blur 要素からフォーカスが外れた
change 要素の値が変化した
click 要素がクリックされた
dblclick 要素がダブルクリックされた
error 画像の読み込みに失敗した
focus 要素にフォーカスが移動した
focusin 要素にフォーカスが移動した
focusout 要素からフォーカスが外れた
keydown キーが押された
keypress キーが押されている
keyup キーを離した
load ページ(要素)がロードされた
mousedown マウスのボタンが押された
mouseenter マウス・ポインタが要素に乗った
mouseleave マウス・ポインタが要素から離れた
mousemove マウス・ポインタが要素の中で移動
mouseout マウス・ポインタが要素から離れた
mouseover マウス・ポインタが要素に乗った
mouseup マウスのボタンを離した
resize ウィンドウをリサイズ
scroll スクロールした
select テキストボックス/テキストエリアのテキストを選択した
submit フォームをサブミットした
unload ページをアンロード



4. イベントハンドラとアプリケーションロジックを分離する

イベントハンドラとアプリケーションロジックが結合している悪いコードです。

// Bad
function handleClick(event) {
  var popup = document.getElementById('popup');
  popup.style.left = event.clientX + 'px';
  popup.style.top  = event.clientY + 'px';
  popup.className  = 'reveal';
}

$('#element').on('click', handleClick());


まずは、「イベントハンドラとアプリケーションロジックを切り分ける」ことを行います。
showPopupメソッドを新たに作り、イベントハンドラからアプリケーションロジックを切り分けます。
こうすることで、アプリケーションロジック(shosPopup)を複数の地点から呼び出すことができるようになる。

var MyApp = {

  handleClick: function(event) {
    // showPopupにアプリケーションロジックを分離する
    this.showPopup(event);
  },

  // showPopupにアプリケーションロジックを分離する
  showPopup: function(event) {
    var popup = document.getElementById('popup');
    popup.style.left = event.clientX + 'px';
    popup.style.top  = event.clientY + 'px';
    popup.className  = 'reveal';
  }
};

$('element').on('click', function(event) {
  MyApp.handleClick(event);
});


次に、「イベントオブジェクト(event)を引き回さない」ようにします。
イベントハンドラで引き渡されるイベントオブジェクト(event)は多くの情報を持っています。
便利なのですが、eventを関数の引数として引き回すと、関数で必要な情報がわかりづらいのでコードの可読性が下がってしまいます。
そのため、必要な値だけを渡すようにします。

showPopupメソッドは、eventオブジェクトのX, Y座標のみしか使わないので、handleClickメソッドからは、その2つのみを引数で渡すようにします。
こうすることで、showPopupに必要な値が明確になるので、より他のメソッドから呼びやすくなり、テストもしやすくなります。

var MyApp = {

  handleClick: function(event) {
    // X, Y座標のみを渡す
    this.showPopup(event.clientX, event.clientY);
  },

  showPopup: function(x, y) {
    var popup = document.getElementById('popup');
    popup.style.left = x + 'px';
    popup.style.top  = y + 'px';
    popup.className  = 'reveal';
  }
};

$('element').on('click', function(event) {
  MyApp.handleClick(event);
});


さらに、jQueryのバブリング(伝播)のキャンセル処理を追加する場合は次のようにします。

handleClick: function(event) {
  // DOM Level 2イベントのサポートが前提
  event.preventDefault();  // その要素のイベントをキャンセル
  event.stopPropagation(); // 親要素への伝播をキャンセル

  // アプリケーションロジックの実行
  this.showPopup(event.clientX, event.clientY);
}

参考文献

  • 独習JavaScript 第2版
  • メンテナブルJavaScript