1. ホーム
  2. javascript

[解決済み] Knockout.jsは準大規模データセットでは信じられないほど遅い

2023-05-26 03:47:16

質問

私はKnockout.jsを使い始めたばかりです(ずっと試してみたかったのですが、今ようやく言い訳ができました!) - しかし、比較的小さなデータセット(およそ400行ほど)にテーブルをバインドする際に、本当にひどいパフォーマンスの問題に遭遇しています。

私のモデルにおいて、私は次のコードを持っています。

this.projects = ko.observableArray( [] ); //Bind to empty array at startup

this.loadData = function (data) //Called when AJAX method returns
{
   for(var i = 0; i < data.length; i++)
   {
      this.projects.push(new ResultRow(data[i])); //<-- Bottleneck!
   }
};

問題は for のループで、400行程度で約30秒程度かかることです。 しかし、このコードを変更すると

this.loadData = function (data)
{
   var testArray = []; //<-- Plain ol' Javascript array
   for(var i = 0; i < data.length; i++)
   {
      testArray.push(new ResultRow(data[i]));
   }
};

次に for のループは瞬く間に完了します。 つまり push のメソッドは、Knockout の observableArray オブジェクトは信じられないほど遅いです。

以下は私のテンプレートです。

<tbody data-bind="foreach: projects">
    <tr>
       <td data-bind="text: code"></td>
       <td><a data-bind="projlink: key, text: projname"></td>
       <td data-bind="text: request"></td>
       <td data-bind="text: stage"></td>
       <td data-bind="text: type"></td>
       <td data-bind="text: launch"></td>
       <td><a data-bind="mailto: ownerEmail, text: owner"></a></td>
    </tr>
</tbody>

私の質問

  1. これは、私のデータ(AJAXメソッドから来る)をobservableコレクションにバインドする正しい方法でしょうか?
  2. 私は push は、私がそれを呼び出すたびに、バインドされたDOMオブジェクトを再構築するなど、何らかの重い再計算を行うものと思われます。 この再計算を遅らせるか、あるいは、すべてのアイテムを一度に押し込む方法はありますか?

必要であれば、さらにコードを追加することができますが、これが関連するものであることは間違いありません。 ほとんどの場合、私はサイトからKnockoutチュートリアルに従っただけです。

UPDATEです。

以下のアドバイスに従って、コードを更新しました。

this.loadData = function (data)
{
   var mappedData = $.map(data, function (item) { return new ResultRow(item) });
   this.projects(mappedData);
};

しかし this.projects() は400行で10秒程度かかります。 確かに、これがどの程度の速度になるかは分かりませんが を使用せずに Knockout を使用しない場合(DOM を通して行を追加するだけ)には、10 秒よりはるかに速くなるような気がします。

UPDATE 2です。

以下の他のアドバイスに従って、私は jQuery.tmpl を試してみました (KnockOut でネイティブにサポートされています)。このテンプレート エンジンは、わずか 3 秒強で約 400 行を描画します。 これは、スクロールするとより多くのデータが動的にロードされるようなソリューションを除けば、最良のアプローチのように思えます。

どのように解決するのですか?

コメントで提案されているとおりです。

Knockoutは(foreach, with)バインディングに関連した独自のネイティブテンプレートエンジンを持っています。また、他のテンプレートエンジン、すなわちjquery.tmplもサポートしています。読む はこちら をご覧ください。異なるエンジンでのベンチマークは行っていませんので、参考になるかどうかはわかりません。前のコメントを読むと、IE7では、あなたが求めているパフォーマンスを得るのに苦労するかもしれません。

余談ですが、KO は、誰かがそのためのアダプタを書いたのであれば、どんな js テンプレート エンジンでもサポートします。jquery tmpl は次のものに置き換えられる予定なので、他のものを試してみるとよいでしょう。 JsRender .