Knockout.js 日本語ドキュメント

"event" バインディング

用途

event バインディングは、関連付けられた DOM エレメントで任意のイベントが発生したときに、 指定した JavaScript 関数を実行するイベントハンドラを追加することを可能にします。 keypressmouseover, mouseout などどのようなイベントでもバインドできます。

<!-- View -->
<div>
	<div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }">
		カーソルをここに合わせて下さい。
	</div>
	<div data-bind="visible: detailsEnabled">
		なんらかの詳細メッセージ
	</div>
</div>
// ViewModel
var viewModel = {
	detailsEnabled: ko.observable(false),
	enableDetails: function() {
		this.detailsEnabled(true);
	},
	disableDetails: function() {
		this.detailsEnabled(false);
	}
};
ko.applyBindings(viewModel);

最初のエレメントにマウスカーソルが 乗る or 離れる と同時に、ViewModel の detailsEnabled を切り替えるメソッドが実行されます。 2つ目のエレメントは detailsEnabled の値の変化に応じて、表示/非表示 が切り替わります。

  • 主パラメタ

    プロパティを対象のイベント名、値を対象のイベントにバインドしたい関数にした JavaScript オブジェクトです。

    どんな JavaScript 関数も使用できます。ViewModel の関数である必要は、必ずしもありません。
    event: { mouseover: someObject.someFunction } のように書くことで、どんなオブジェクトの関数も参照できます。

  • 追加パラメタ

    なし

(注1) ハンドラ関数に引数として“現在のアイテム”が渡される

ハンドラを呼び出す際、Knockout は第一引数として現在のモデルを渡します。 これは、特に配列の各要素を表示し、さらにどのアイテムの UI がクリックされたのかを知る必要があるときに便利です。

<ul data-bind="foreach: places">
	<li data-bind="text: $data, event: { mouseover: $parent.logMouseOver }"> </li>
</ul>
<p><span data-bind="text: lastInterest"> </span> に興味がお有りですか?</p>

<script type="text/javascript">
	function MyViewModel() {
		var self = this;
		self.lastInterest = ko.observable();
		self.places = ko.observableArray(['London', 'Paris', 'Tokyo']);

		// 第一引数として現在のアイテムが渡されるため、どの地名がマウスオーバーされたのかがわかる
		self.logMouseOver = function(place) {
			self.lastInterest(place)
		}
	}
	ko.applyBindings(new MyViewModel());
</script>

上記サンプルのポイントは2つあります:

  • foreachwith の内部のように、 ネストされた バインディング・コンテキスト の中でルート ViewModel やその他親のコンテキストのハンドラ関数を呼び出す場合、 ハンドラ関数を示すために $parent $root といったプレフィックスを使う必要があります。
  • ViewModel にて、 this の別名として self 変数を定義すると便利です。 this を再定義することで、イベントハンドラや Ajax リクエストのコールバックで発生する 問題を事前に回避 することができます。

(注2) イベントオブジェクトにアクセスする、またはさらなる引数を渡す

場合によっては、イベントの DOM イベントオブジェクトにアクセスする必要がありますよね。 Knockout は、次の例のようにイベントオブジェクトを第二引数として関数に渡します。

<div data-bind="event: { mouseover: myFunction }">
	ここにマウスをのせる
</div>

<script type="text/javascript">
	var viewModel = {
		myFunction: function (data, event) {
			if (event.shiftKey) {
				// Shift キーが押されていた時のアクション
			} else {
				// 通常のアクション
			}
		}
	};
	ko.applyBindings(viewModel);
</script>

さらに引数を渡す方法として、まずハンドラを、引数を受け渡す関数リテラルでラップする方法があります。

<div data-bind="event: { mouseover: function(data, event) { myFunction('引数1', '引数2', data, event) } }">
	ここにマウスをのせる
</div>

Knockout は関数リテラルにデータとイベントオブジェクトを渡すため、ハンドラに渡すことができるということになります。

別の方法として、関数リテラルを View に記述するのは避けたいのならば bind 関数を使いましょう。 次のように、関数を呼び出す際の引数を指定することができます。

<div data-bind="event: { mouseover: myFunction.bind($data, '引数1', '引数2') }">
	ここにマウスをのせる
</div>

(注3) デフォルトのクリックの挙動を許可する

通常、Knockout はクリックイベントによるデフォルトの挙動を抑止します。 これは、もし input タグの keypress イベントを捕捉するために event バインディングを使用した場合、 例えば、ブラウザはハンドラ関数を呼び出すのみで input 要素の値を追加しません。 より一般的な例として、event バインディングを内部で利用している click バインディング も同じくハンドラ関数を呼び出すのみで リンク先への画面遷移を行いません。 通常は click バインディングにてリンクは、ハイパーリンクではなく ViewModel を操作するための UI 部品として使われるためこのような仕様となっています。

もしもクリックイベントのデフォルトの挙動を行わせたい場合は、 click のハンドラ関数にて true を返却してください。

(注4) イベントバブリングを抑止する

通常、Knockout はイベントが上位の要素のイベントハンドラにバブリングすることを許可します。 例えば、ある要素とその親要素がどちらも mouseover イベントをハンドリングするとします。 このときこの要素がクリックされると、両方の要素にてハンドラが呼び出されます。 必要であれば、 (イベント名)Bubble という追加バインディングに false を指定することでバブリングを抑止することができます。

<div data-bind="mouseover: myDivHandler">
	<button data-bind="mouseover: myButtonHandler, mouseoverBubble: false">
		ここにカーソルをのせる
	</button>
</div>

この場合通常であれば myButtonHandler が最初に呼び出され、 イベントは myDivHandler に遡及します。 しかし、付与された mouseoverBubble バインディングの false 指定によってイベントの遡及は myButtonHandler を通過後に止まります。

依存

Knockout コアライブラリ以外、なし。

原文はこちら

side menu