3

Knockout のほとんどは非常に直感的です。私にとって奇妙なことの 1 つは、マッピング プラグインの仕組みです。私は、ajax 呼び出しから JSON をフィードし、HTML で参照できる一種の「動的」ビュー モデルを使用できることを期待/期待していました。

マッピングプラグインの説明は、次のように聞こえます。

「データ構造がより複雑になると (たとえば、子が含まれたり、配列が含まれたりすると)、手動で処理するのが非常に面倒になります。マッピング プラグインを使用すると、通常の JavaScript オブジェクト (または JSON 構造) からオブザーバブルへのマッピングを作成できます。モデルを表示します。」

しかし、実際にはコードで最初にビュー モデルを定義する必要があるようです。その後、マッピング プラグインといくつかの JSON データを使用して、後でビュー モデルを設定できます。これは正しいですか?

私がやろうとしていたことの具体例。

Solr (JSON 検索結果を返す検索エンジン) で Knockout を使用しようとしています。Solr によって返される JSON データのスケルトン構造は次のとおりです。

  {
      "responseHeader": {
          "status": 0,
          "QTime": 0,
          "params": {
              "facet": "true",
              "facet.field": "System",
              "q": "testphrase",
              "rows": "1",
              "version": "2.2"
          }
      },
      "response": {
          "numFound": 0,
          "start": 0,
          "maxScore": 0.0,
          "docs": []
      },
      "facet_counts": {
          "facet_queries": {},
          "facet_fields": {
              "System": []
          },
          "facet_dates": {},
          "facet_ranges": {}
      },
      "highlighting": {}
  }

実際、これは、最初に設定したときに、マップされたビュー モデルに入力している構造です。

JSON データが Solr からどのように返されるかについて少し理解していただくために、response.docs 配列にはハッシュの配列が含まれており、ハッシュ データはインデックス付けされたドキュメント データのキー/値で構成されています。配列内の各ハッシュは、検索結果で返される 1 つのドキュメントです。

その部分はうまくマッピングされているようです。

JSON の「ハイライト」部分が問題の原因です。HTML で強調表示フィールドを参照しようとすると、ReferenceErrors が発生します。JSON で強調表示フィールドがどのように見えるかの例を次に示します。

"highlighting": {
    "2-33-200": {
        "Title": ["1992 <b>Toyota</b> Camry 2.2L CV Boots"]
    },
    "2-28-340": {
        "Title": ["2003 <b>Toyota</b> Matrix 2.0L Alignment"]
    },
    "2-31-2042": {
        "Title": ["1988 <b>Toyota</b> Pickup 2.4L Engine"]
    }
}

各 response.docs 要素を解析しようとする HTML に foreach があり、オブジェクトの強調表示部分にそのドキュメントの Id フィールドとの一致が含まれている場合、デフォルトのタイトルではなく、強調表示されたタイトルに置き換えたいと考えています。(以下のコードでは、「Results」は、JSON をマッピングしているビューモデルの名前です。)

<div id="search-results" data-bind="foreach: Results.response.docs">
    <div data-bind="attr: { id: 'sr-' + Id }" class="search-result">
        <h3 class="title"><a data-bind="html: (($root.Results.highlighting[Id]['Title'] != undefined) ? $root.Results.highlighting[Id]['Title'] : Title), attr: {href: Link}"></a></h3>
        <span class="date" data-bind="text: DateCreated"></span>
        <span class="snippet" data-bind="html: Snippet"></span>
    </div>
</div>

これを使用しようとすると、常に次のエラーが発生します。

Uncaught Error: Unable to parse bindings.
Message: TypeError: Cannot read property 'Title' of undefined;
Bindings value: html: (($root.Results.highlighting[Id]['Title'] != undefined)  ? $root.Results.highlighting[Id]['Title'] : Title), attr: {href: Link}

データを参照する方法のバリエーションを試しましたが、アクセスできないようです。

編集私は少し前進しています。私のマッピング定義では、次のように「強調表示」を指定します。

"highlighting": ko.observable({})

強調表示を {} に設定するだけではありません。これで、マッピングを行うときに、ハイライト データを少し覗くことができます。それでも、まだ奇妙なエラーが表示されます。

テスト HTML コードを単純化して、各検索結果のハイライト データを吐き出すだけにしました。

<div id="search-results" data-bind="foreach: Results.response.docs">
    <pre data-bind="text: JSON.stringify(ko.toJS($root.Results.highlighting()[Id()]), null, 2)"></pre>
</div>

<pre>これにより、次のような複数のタグが返されます。

{
  "Title": [
    "1992 <b>Toyota</b> Camry 2.2L CV Boots"
  ]
}

ただし、その HTML コードを次のように変更すると:

<pre data-bind="text: $root.Results.highlighting()[Id()]['Title']"></pre>

次のようなエラーが引き続き発生します。

Message: TypeError: Cannot read property 'Title' of undefined;
Bindings value: text: $root.Results.highlighting()[Id()]['Title']

私には意味がありません!以前のテストでは、利用可能なデータに「タイトル」キーが含まれていることが示されましたが、なぜそのデータにアクセスできないのですか?

編集jsfiddleを作成しましたが、もちろん...期待どおりに動作します。jsfiddle で問題を再現できません。:-(

編集OK 私はここでいくらか前進していますが、何が起こっているのかまだ非常に混乱しています。まず、デバッグ HTML を次のように変更しました。

<div id="search-results" data-bind="foreach: Results.response.docs">
    <pre data-bind="text: console.log($root.Results.highlighting()[Id()])"></pre>
</div>

その後、ajax 呼び出しを送信したところ、Chrome コンソールに次の出力が表示されました。

undefined
undefined
> Object

したがって、何らかの理由で、foreachループは 3 つの Results.response.docs をループしており、最初の 2 つはハイライト() オブジェクトの何にもマッピングされていないため、未定義を返しています。プロパティは失敗していました。

これを確認するために、ko if: $root.Results.highlighting()[Id()]そのブロックを a で囲み、最終的に foreach ループ中に .Title プロパティに JS エラーなしでアクセスできました。

これにより、なぜ/どのように 3 つの Results.response.docs オブジェクトがループされているのかという疑問が残ります。おそらく foreach バインディングが 3 回実行され、最初の 2 回は強調表示オブジェクトが空で、3 回目は最終的に入力されているのでしょうか? しかし、私はそれがなぜなのかを理解するのに苦労しています。

もう 1 つの考えられる手がかり: ページをリロードせずに 2 回目の ajax 呼び出しをトリガーすると、これら 3 つの「パス」がすべて、コンソール ログで毎回有効なオブジェクトを返すことがわかります。したがって、2 つundefinedの と 1 つのオブジェクトの代わりに、3 つのオブジェクトがすべて並んでいます。

ただし、HTML 出力では、1 行のデータしか表示されません。これは、3 つの要素をループしているのではなく、実際には 3 回実行されていることを証明しているようです。問題は残ります...なぜですか?

4

1 に答える 1

3

マッピングプラグインは期待どおりに機能しています。問題は、プラグインがオブジェクトのすべてのレベルでオブザーバブルを作成することを期待していることです。これはプラグインの動作方法ではありません。「leaf」プロパティのオブザーバブルのみを作成します。したがって、あなたの場合$root.Results.highlighting、オブザーバブルとして作成されていません。ただし、ドキュメントのidプロパティはオブザーバブルとして作成されるため、解決策はです。

$root.Results.highlighting[Id()]

あなたのフィドルの1つが自己を割り当てていたので、あなたは混乱しているかもしれないと思います。結果は2回で、実際には問題が隠されていたときに一方向に機能しているように見えました。

これが作業バージョンです

http://jsfiddle.net/madcapnmckay/UaBKe/

お役に立てれば。

于 2012-04-03T18:30:18.853 に答える