KnockoutJSのテンプレートバインディングエラーをデバッグする方法


199

KnockoutJSテンプレートのデバッグに関する問題が解決しません。

items」というプロパティにバインドしたいが、テンプレートでタイプミスを作成し、(存在しない)プロパティ「item」にバインドするとします。

Chromeデバッガーを使用すると、次のことがわかります。

"item" is not defined.

バインディングの問題に関する詳細情報を取得するのに役立つツール、テクニック、コーディングスタイルはありますか?

回答:


344

特定のスコープで利用可能なデータに問題がある場合によく行うことの1つは、テンプレート/セクションを次のようなものに置き換えることです。

<div data-bind="text: ko.toJSON($data)"></div>

または、もう少し読みやすいバージョンが必要な場合:

<pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>

これにより、そのスコープでバインドされているデータが吐き出され、適切にネストしていることを確認できます。

更新:KO 2.1以降、次のように簡略化できます。

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

これで、引数がに渡されJSON.stringifyます。


おお。私もこの質問をする必要があります。複雑なコードを使用してconsole.logデータに記録しました。今でははるかに簡単です。
AlfeG

3
デバッグのヒントについてもっと考えて、ブログ投稿をする必要があるかもしれません。頭に浮かぶもう1つの方法は、オブザーバブルまたは計算されたオブザーバブルに対して手動でサブスクリプションを実行して、値の変化を監視することです。以下のような場合nameに観察やっているname.subscribe(function(newValue) { console.log("name", newValue); });
RPニーマイヤー

1
この回答は比較的古いためかもしれませんが、console.logを使用して、オブジェクトのプロパティを表示するためにデバッガーの全機能を活用してみませんか?ie:stackoverflow.com/a/16242988/647845を
Dirk Boer 14年

1
@DirkBoer-console.logを使用することも素晴らしい方法です。foreachシナリオのように要素の横にデータを表示したいことがよくありますが、関連するレンダリングされたマークアップ内のページをコンソールでふるいにかけるよりも簡単に確認できます。状況によります。ここでの私の考えのいくつか:knockmeout.net/2013/06/…。また、のように「クリーン」バージョンをバインディングに記録することもできますconsole.log(ko.toJS(valueAccessor())
RPニーマイヤー2014年

1
@RuneJeppesen-シリアル化しているデータの種類はわかりませんが、次のようなものが役立ちます。knockmeout.net
RP Niemeyer

61

開発にChromeを使用している場合は、Knockoutjsコンテキストデバッガーと呼ばれる非常に優れた拡張機能(私とは関係ありません)があり、開発者ツールの[要素]パネルにバインディングコンテキストが直接表示されます。


3
FirefoxまたはFirebugにこれがあったらいいのに。誰もがそのようなことを知っていますか?
Patrick Szalapski、2014年

サポートが削除されたようです。複雑なデータバインド構造を使用すると、Chromeがクラッシュします。約1年間、私のプロジェクトで働いていません。
北極圏

久しぶりにKOからEmberに移りました。
neverfox '31年

1
それは(ほとんど)私にとってはうまくいき、私はいくつかの本当に複雑な構造を持っています。私は試していませんが、拡張機能のオプションで、「クラッシュが発生した場合は、おそらくシリアル化できないビューモデルがあります。シリアル化をオフにすることができます。」この機能を無効にするためのメッセージの下にチェックボックスがあります。
Grinn、2015

tyはすぐにとても便利です。
アンドリュー

37

JavaScriptライブラリファイルのどこかにbindingHandlerを1回定義します。

ko.bindingHandlers.debug = 
{
    init: function(element, valueAccessor) 
    {
        console.log( 'Knockoutbinding:' );
        console.log( element );
        console.log( ko.toJS(valueAccessor()) );
    }
};

次のように単純に使用するよりも:

<ul data-bind="debug: $data">

メリット

  • Elements PanelのRevealなど、Chromeデバッガの全機能を使用する
  • デバッグのためだけに、DOMにカスタム要素を追加する必要はありません

ここに画像の説明を入力してください


32

役に立つ別のものが見つかりました。いくつかのバインディングをデバッグしていて、Ryansの例を使用してみました。JSONが循環ループを検出したというエラーが発生しました。

<ul class="list list-fix" data-bind="foreach: detailsView().tabs">
 <li>
   <pre data-bind="text: JSON.stringify(ko.toJS($parent), null, 2)"></pre>
   <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
 </li>
</ul>

ただし、このアプローチを使用すると、データバインド値が次のように置き換えられます。

  <ul class="list list-fix" data-bind="foreach: detailsView().tabs">
    <li>
      <pre data-bind="text: 'click me', click: function() {debugger}"></pre>
      <a href="#" data-bind="click: $parent.setActiveTab, text: title"></a>
    </li>
  </ul>

クロームデバッグウィンドウを開いた状態でPRE要素をクリックすると、スコープ変数ウィンドウが表示されます。

それのための少し良い方法を見つけました:

<pre data-bind="text: ko.computed(function() { debugger; })"></pre>

本当に便利です。<pre data-bind = "text:ko.toJSON($ data、null、2)"> </ pre>を使用して、ノックアウト循環ループとRazorマークアップの問題が発生していました。<pre ... debugger>は完全な回避策です。何らかの理由で、@ Html.CheckBoxのようなRAZOR入力がko.toJSONを壊していました。
北極圏

20

ステップバイステップガイド

  1. このガイドでは、公式のKnockoutJSサンプルの 1つを使用します。
  2. 2番目の連絡先(宮城先生)の背後にあるデータを表示するとします。
  3. 2番目の連絡先の最初の入力ボックス(テキスト「Sensei」が付いているもの)を右クリックします。
  4. 「要素の検査」を選択します。Chromeデベロッパーツールバーが開きます。
  5. JavaScriptコンソールウィンドウを開きます。コンソールにアクセスするに>=は、Chromeデベロッパーツールバーの左下にあるアイコンをクリックするか、Chromeデベロッパーツールバーの[コンソール]タブを開くか、Ctrl+ Shift+J
  6. 次のコマンドを入力して、Enterキーを押します。 ko.dataFor($0)
  7. 2行目にバインドされているデータが表示されます。オブジェクトの左にある小さな三角形を押してオブジェクトツリーを移動することにより、データを展開できます。
  8. 次のコマンドを入力して、Enterキーを押します。 ko.contextFor($0)
  9. これで、ルートとすべての親を含むKnockoutコンテキスト全体を含む複雑なオブジェクトが表示されます。これは、複雑なバインディング式を記述していて、さまざまな構成を試してみたい場合に便利です。

上記のガイドに従った場合の出力例

この黒魔術とは何ですか?

このトリックは、Chromeの$ 0〜$ 4の機能KnockoutJSのユーティリティメソッドを組み合わせたものです。要するに、Chromeはあなたがクロームデベロッパーツールバーで選択している要素を記憶し、エイリアスの下でこれらの要素を公開します$0$1$2$3$4。そのため、ブラウザーで要素を右クリックして[要素の検査]を選択すると、この要素がエイリアスの下で自動的に使用可能になります$0。このトリックは、KnockoutJS、AngularJS、jQuery、またはその他のJavaScriptフレームワークで使用できます。

裏技は、KnockoutJSのユーティリティメソッドko.dataForとko.contextForです。

  • ko.dataFor(element) -要素に対するバインドに使用できたデータを返します
  • ko.contextFor(element) -DOM要素で使用できたバインディングコンテキスト全体を返します。

ChromeのJavaScriptコンソールは完全に機能するJavaScriptランタイム環境です。これは、変数を見るだけに限定されないことを意味します。の出力を保存ko.contextForし、コンソールから直接ビューモデルを操作できます。var root = ko.contextFor($0).$root; root.addContact();何が起こるか試してみてください:-)

幸せなデバッグ!


7

私が使用する本当にシンプルなものをチェックしてください:

function echo(whatever) { debugger; return whatever; }

または

function echo(whatever) { console.log(whatever); return whatever; }

次に、htmlでは、あなたが持っていたと言います:

<div data-bind="text: value"></div>

と交換するだけ

<div data-bind="text: echo(value)"></div>

より高度な:

function echo(vars, member) { console.log(vars); debugger; return vars[0][member]; }

<div data-bind="text: echo([$data, $root, $parents, $parentContext], 'value')"></div>

楽しい :)

更新

もう1つの厄介なことは、未定義の値にバインドしようとしている場合です。上記の例で、データオブジェクトが{value: 'some text'}ではなく{}であると想像してください。この場合、問題が発生しますが、次の調整で問題ありません。

<div data-bind="text: $data['value']"></div> 

5

これらのエラーを視覚化するために、knockthrough.jsというgithubプロジェクトを作成しました。

https://github.com/JonKragh/knockthrough

バインディングエラーを強調表示し、そのノードのデータコンテキストのダンプを提供します。

ここでサンプルを試すことができます:http : //htmlpreview.github.io/?https : //github.com/JonKragh/knockthrough/blob/master/default.htm

ここに画像の説明を入力してください

この点に私を導いてくれたSOの優れたノックアウトコードサンプルのRP Niemeyerの功績です。


3

バインディングに渡されるデータを確認する最も簡単な方法は、データをコンソールにドロップすることです。

<div data-bind="text: console.log($data)"></div>

Knockoutはテキストバインディングの値を評価し(実際にはここで任意のバインディングを使用できます)、$ dataをコンソールのブラウザーパネルにフラッシュします。


2

他のすべての答えはうまくいきます、私がしたいことを追加しています:

ビューで(すでにViewModelをバインドしていると仮定します):

<div data-bind="debugger: $data"></div>

ノックアウトコード:

ko.bindingHandlers.debugger = {
    init: function (element, valueAccessor) {
        debugger;
    }
}

これは、デバッガでコードを一時停止し、elementかつvalueAccessor()貴重な情報が含まれています。


カスタムバインディングは必要ありません。stackoverflow.com/documentation/knockout.js/5066/…をご覧ください
Adam Wolski

1
うん、私はそれをこの方法を行うための明確な必要性がない同意、私は単にこれは1つのデバッグのスタイルであることを指摘したかった...誰もが独自の方法でそれをやってのように思える:)
アーディティヤMP

1

Visual StudioとIEで開発している場合data-bind="somebinding:(function(){debugger; return bindvalue; })()"は、evalファイルではなくすべてのバインディングを使用してスクリプトに移動し、$ context $ data(これもChromeで);


私はそれがVisual StudioやIEとは何の関係もないと思います。
Serhiy

@Serhiy chromeでも同じですが、chromeではそれなしでファイルにアクセスできたと思います。VSでファイルにアクセスできるとは思いません。
フィリップコルダス2017年

0

これは私にとってはうまくいきます:

<div data-bind="text: function(){ debugger; }()"></div>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.