Knockout.js/clickバインディング
Knockout.jsのclickバインディングとは、DOM要素がクリックされたときに、パラメーターで指定されたJavaScript関数が呼び出されるようにする操作バインディングである。
クリックと言えば主にHTMLのbuttonタグやinputタグ、aタグで使われると思うが、それ以外にも目に見えているDOM要素であれば何でもclickバインディングを付けることができる。
clickバインディングは、基本的にeventバインディングのうち、多用されるであろうクリックイベントを短縮表記できるようにしたものなので挙動は同一である。よって、「eventバインディング」のページも見ろ。
パラメーター[編集 | ソースを編集]
clickバインディングの基本的な書式は以下のとおりである。
<button data-bind="click: 関数名または匿名関数">押してみろ!</button>
<div data-bind="click: 関数名または匿名関数">クリックしてみろ!</div>
clickバインディングのパラメーターにはクリックした際に実行したいビューモデルの関数名を指定する。
また「click: someObject.someFunction」と記述することでビューモデル以外の任意のJavaScriptの関数を指定することもできる。さらに「click: function(data, event) {}」と匿名関数を記述することもできたりする。
追加パラメーター[編集 | ソースを編集]
clickBubble[編集 | ソースを編集]
clickバインディングが入れ子になっていて、かつ子要素側でクリックされると、knockout.jsはデフォルトで親要素のclickバインディングまで実行してしまう。
そのようなことを抑制したい場合には、clickBubbleパラメーターに「false」を設定する。そうすることで親要素へのイベントの伝搬は停止される。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockout.js - clickバインディング</title>
<script type="text/javascript" src="jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript">
jQuery(function() {
// ビューモデル
var AppViewModel = function() {
var self = this;
self.divClick = function() {
alert("div click!");
};
self.buttonClick = function() {
alert("button click!");
};
};
// バインディング適用
ko.applyBindings(new AppViewModel());
});
</script>
</head>
<body>
<div data-bind="click: divClick">
<button data-bind="click: buttonClick">
押してみろ!その1
</button>
<button data-bind="click: buttonClick, clickBubble: false">
押してみろ!その2
</button>
</div>
</body>
</html>
備考[編集 | ソースを編集]
clickで指定された関数には「現在のアイテム」を渡す[編集 | ソースを編集]
withバインディングやforeachバインディングのブロック内でclickバインディングを用いると、clickで呼ばれる関数の第一引数にwithやforeachで展開された各オブジェクトが自動的に渡される。
なお、ブロックの外側でclickバインディングを使うと第一引数にビューモデルが丸ごと渡される。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockout.js - clickバインディング 001</title>
<script type="text/javascript" src="jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript">
jQuery(function() {
// ビューモデル
var AppViewModel = function() {
var self = this;
self.places = ko.observableArray([
{ name: 'London', japanese: 'ロンドン' },
{ name: 'Paris' , japanese: 'パリ' },
{ name: 'Tokyo' , japanese: '東京' },
]);
self.removePlace = function(val) {
// valはself.places内の各オブジェクト
self.places.remove(val);
};
self.clickButton = function(val) {
// valはAppViewModelインスタンス(≒この例ではselfと同じモノ)
alert(val);
};
};
// バインディング適用
ko.applyBindings(new AppViewModel());
});
</script>
</head>
<body>
<ul data-bind="foreach: places">
<li>
<span data-bind="text: $data.name"></span>
<button data-bind="click: $parent.removePlace">削除</button>
</li>
</ul>
<button data-bind="click: clickButton">押すな!</button>
</body>
</html>
みどころ1[編集 | ソースを編集]
withバインディングやforeachバインディングのブロック内で入れ子になっている場合は、各種バインディングの際に「$parent」や「$root」などのプレフィックスを付ける必要がある。
詳細はforeachバインディングの項目を参照。
みどころ2[編集 | ソースを編集]
AppViewModelオブジェクト内のコンストラクタでthis変数をself変数に代入しているが、これは主にAJAXを使ったときの結果受信時に非同期で呼ばれるコールバック関数内でthis変数が再定義されてしまう問題を回避するためである。
この例ではthis変数もself変数も同じものだが、後々のことを考えてそういう風にしておきましょうという、一種の[[JavaScript]界でよく使われるデザインパターンだそうだ。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockout.js - clickバインディング 001</title>
<script type="text/javascript" src="jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript">
jQuery(function() {
// ビューモデル
var AppViewModel = function() {
var self = this;
self.clickButton = function(val) {
// これ true
alert(this == self);
jQuery.get("021_click.html", null, function(val) {
// これ false
alert(this == self);
});
};
};
// バインディング適用
ko.applyBindings(new AppViewModel());
});
</script>
</head>
<body>
<button data-bind="click: clickButton">押すな!</button>
</body>
</html>
既定のクリックアクションを有効化する[編集 | ソースを編集]
knockout.jsでclickバインディングを設定すると、既定のクリックアクションが無効化される。たとえばHTMLのaタグにclickバインディングを適用してあると、hrefプロパティで指定されたリンク先へは飛ばなくなる。
これでは困るという場合には、clickバインディングで指定した関数が戻り値としてtrueを返すようにすると、既定のクリックアクションを有効化することができる。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>knockout.js - clickバインディング</title>
<script type="text/javascript" src="jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="knockout-2.0.0.js"></script>
<script type="text/javascript">
jQuery(function() {
// ビューモデル
var AppViewModel = function() {
var self = this;
// 飛ばない
self.clickButton = function(val) {
alert("click!");
};
// return trueで<a href="">のリンク先へ飛ぶ
self.clickButtonWithJump = function(val) {
alert("click!");
return true;
};
};
// バインディング適用
ko.applyBindings(new AppViewModel());
});
</script>
</head>
<body>
<a data-bind="click: clickButton" href="http://search.yahoo.co.jp/search?p=site%3Amonobook.org">Yahoo検索1</a><br/>
<a data-bind="click: clickButtonWithJump" href="http://search.yahoo.co.jp/search?p=site%3Amonobook.org">Yahoo検索2</a><br/>
</body>
</html>