knockout.js
バインディング
サーチ…
構文
-
<!-- ko if:myObservable --><!-- /ko -->
-
<i data-bind="if:myObservable"></i>
備考
バインディングとは
基本的にバインディングまたはデータバインディングは、ViewModelをビュー(テンプレート)にリンクする方法で、その逆もあります。 KnockoutJSは双方向データバインディングを使用しています。つまり、ViewModelへの変更はViewに影響し、Viewへの変更はViewModelに影響します。
フードの下で(短い概要)
バインディングは、特定のタスクを解決するためのプラグイン(スクリプト)です。このタスクは、あなたのViewModelに従ってマークアップ(html)を変更することが多いです。
たとえば、 text
バインディングを使用すると、ViewModelが変更されるたびにテキストを表示し、動的に変更することができます。
KnockoutJSには多くの強力なバインディングが付属しており、独自のカスタムバインディングで拡張することができます。
そして最も重要なのは、バインディングは魔法ではなく、一連のルールに従って動作し、バインディングが何であるか、どのパラメータが必要なのか、バインディングのソースコードを参照できるビューをいつ更新するのかは不明です。
カスタムバインディングの次の例を考えてみましょう。
ko.bindingHandlers.debug = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.computed(function () {
var value = ko.unwrap(valueAccessor());
console.log({
value: value,
viewModel: viewModel,
bindingContext: bindingContext
});
}, null, { disposeWhenNodeIsRemoved: element });
}
};
- バインディングには名前 -
debug
がありますので、次のように使用できます。
data-bind="debug: 'foo'"
-
init
メソッドは、バインディングが開始されると一度呼び出されます。残りの更新は、element
が削除されたときに配置される匿名計算によって処理されます。 - この値は
foo
(この値は、ko.unwrap
メソッドを使用して読み取ることができるため、この値も現在のviewModelとbindingContextです)。 - 渡された値が変更されるたびに、バインディングは更新された情報をコンソールに出力します。
- このバインディングは、
ko.virtualElements.allowedBindings.debug
フラグがtrueに設定されていないため、仮想要素(htmlコメント)では使用できません。実際の要素でのみ使用できます。
かっこを使用する場合
追加のプラグインがなければ、KnockoutJSはViewModel上のプロパティのライブビュー更新のみを観測可能 (通常observable
、 computed
、 pureComputed
、 observableArray
など)にします。オブザーバブルは次のように作成されます:
var vm = { name: ko.observable("John") };
この場合、 vm.name
は2つのvm.name
「モード」を持つ関数です。
- Getter:引数なしの
vm.name()
は、現在の値を取得します。 - Setter:引数を指定した
vm.name("Johnnyboy")
は、新しい値を設定します。
組み込みのデータバインディングでは、ゲッターフォームをいつでも使用できます。実際にはカッコを省略することもあり、バインディングによって効果的に追加されます。したがって、これらは同等です:
<p data-bind="text: name"></p> ... will work
<p data-bind="text: name()"></p> ... works too
しかし、これは失敗します:
<p data-bind="text: 'Hello, ' + name + '!'"></p> ... FAILS!
値の比較を含めてデータバインディングに値を渡す前に何かをしたいと思うとすぐに、すべてのオブザーバブルの値を適切に "取得"する必要があります。
<p data-bind="text: 'Hello, ' + name() + '!'"></p> ... works
詳細はこのQ&Aも参照してください。
/ ifnotの場合
if
バインディングを使用して、ノードの子要素を作成する必要があるかどうかを判断できます。
<div class="product-info">
<h2> Product1 </h2>
<img src="../products/product1.jpg"/>
<span data-bind="if:featured">
<span class="featured"></span>
</span>
<span data-bind="ifnot:inStock">
<span class="out-of-stock"></span>
</span>
</div>
<script>
ko.applyBindings({
product: {
featured: ko.observable(true),
inStock: ko.observable(false)
}
});
</script>
if
バインディングの逆はifnot
ではif
<div data-bind="ifnot: someProperty">...</div>
は
<div data-bind="if: !someProperty()">...</div>
場合によっては、コンテナを作成することなく要素の存在を制御することはできません(通常、 <li>
<select>
内の<ul>
または<option>
要素の<li>
要素用)
ノックアウトは、次のようなコメントタグに基づいてコンテナレス制御フロー構文でこれを可能にします:
<select>
<option value="0">fixed option</option>
<!-- ko if: featured-->
<option value="1">featured option</option>
<!-- /ko -->
</select>
フォアハ
他の言語で使用されているリピーターと同様です。このバインディングを使用すると、配列内の各項目のhtmlブロックを複製できます。
<div data-bind="foreach:contacts">
<div class="contact">
<h2 data-bind="text:name">
<p data-bind="text:info">
</div>
</div>
<script type="text/javascript">
var contactViewModel = function (data) {
this.name = ko.observable(data.name);
this.info = ko.observable(data.info);
};
ko.applyBindings({
contacts: [
new contactViewModel({name:'Erik', info:'[email protected]'}),
new contactViewModel({name:'Audrey', info:'[email protected]'})
]
});
</script>
我々がループしているとき、コンテキストは配列内の項目になります。この場合、 contactViewModel
インスタンスになりcontactViewModel
。 foreach
内では、
-
$parent
- このバインディングを作成したビューモデル -
$root
- ルートビューモデル(親でもよい) -
$data
- この配列のインデックスにあるデータ -
$index
- レンダリングされたアイテムの(観測可能な)ゼロベースのインデックス
と
with
バインディングは、バインドされたノード内のHTMLを別のコンテキストにバインドします。
<div data-bind="with: subViewModel">
<p data-bind="text: title"></p>
</div>
with
バインディングは、コンテナ要素が適切でない可能性があるコンテナ要素なしで使用することもできます。
<!-- ko with: subViewModel -->
<p data-bind="text: title"></p>
<!-- /ko -->
var vm = {
subViewModel: ko.observable()
};
// Doesn't throw an error on the `text: title`; the `<p>` element
// isn't bound to any context (and even removed from the DOM)
ko.applyBindings(vm);
// Includes the `<p>` element and binds it to our new object
vm.subViewModel({ title: "SubViewModel" });
with
バインディングは、 template
またはforeach
バインディングと多くの類似点を持ちます。
見える
visible
バインディングは、 style="display: none;"
適用することによって要素を非style="display: none;"
拘束力が虚偽と評価されたときにそれに至る。
<input type="text" data-bind="textInput: name"> <span class="error" data-bind="visible: isInvalid">Required!</span>
ko.applyBindings(new ViewModel());
function ViewModel(){
var vm = this;
vm.name = ko.observable("test");
vm.isInvalid = ko.computed(function() {
return vm.name().length == 0;
});
}