7

私は静止画像500x640をcssスプライトで20x20のピースで覆われたフォルダーに置いています。各ピースを表示するために背景位置を設定しています。後で各ピースを操作できるようにするには、このような種類のディスプレイが必要です。

css:

   .piece
        {
            width: 20px;
            height: 20px;
            display: inline-block;
            //display: inline;
            //zoom:1;
        }        

    .ob { background-image: url("/Images/ob.jpg");}

js:

<script id="flipTemplate" type="text/html">
    <div class="piece ob" data-bind="style: { backgroundPosition: viewModel.getLeftValue($index) + ' ' + viewModel.getTopValue($index) }, attr: {cond: Cond, id: Id }, click: viewModel.setClick ">
                </div>
</script>
<script type="text/javascript">
    viewModel = {
        flips: ko.observableArray([]),      

        setClick: function (data, e) {
            e.preventDefault();            
            //doing click
        },

        getLeftValue: function (index) {

            var position = 0;

            var currentLine = div(index(), 25);

            if (currentLine > 0)
                return '-' + (index() - (currentLine * 25)) * 20 + 'px';
            else
                return '-' + index() * 20 + 'px';
        },

        getTopValue: function (index) {

            return '-' + (div(index(), 25)) * 20 + 'px';
        }
    };    

    ko.applyBindings(viewModel);
</script>
function div(val, by){
    return (val - val % by) / by;
}

そのため、パフォーマンスの問題が発生しています。たとえば、OperaとFFの画像の読み込みは約1秒、IEの場合は約3秒ですが、Chromeでは読み込みが非常に遅くなります。ここに画像の説明を入力してください

Chromeですべてのピースを表示するのに約17秒かかります...

ブラウザが画像を取得するために1つのリクエストを実行し、画像から小さな断片を切り取るよりも、Chromeでこれほど時間がかかるのはなぜですか?

パフォーマンスを向上させる方法はありますか? ここに画像の説明を入力してください

CTRL + Refreshを実行しただけで、ここで奇妙な読み込み結果が発生します。 ここに画像の説明を入力してください

更新:ここにサンプルを配置しました:http://bit.ly/TrcCdp

更新: 私のサンプルにはJSON配列があり、800個の要素が含まれているので、それを少なくするかどうかを確認します。たとえば、600〜700個の要素のパフォーマンスは向上していますが、とにかく800個の要素が必要です。

たとえば、要素が600個しかない場合、Chromeの負荷は約6秒に短縮されます。

では、おそらくノックアウト反復テンプレートのどこかで問題が発生する可能性がありますか?

4

3 に答える 3

4

問題は画像ではありません。画像は、スタイルシートまたはスクリプトタグの前の上部にプリロードを配置することで修正できます。

<meta name="viewport" content="width=device-width">

<script type="text/javascript">
    var img = new Image();
    img.src = 'TestApp_files/obm000.jpg';
</script>

<link href="TestApp_files/jquery00.css" rel="stylesheet">
<link href="TestApp_files/jquery01.css" rel="stylesheet">
<!-- ad nauseum -->

この後、画像は170ms(ローカル)で読み込まれます。ただし、ページはその後、何をすべきかを決定しようとして、さらに10〜15秒間マックします。

根本的な問題は、javascriptが絶対的な混乱であるということです。画像/ファイル/関数の名前はわかりにくいです。ページの中央にあるものは、最後のコードに依存します。最初のコードに依存します。最後のコードに依存します。コントローラー/ビュー/モデルロジックはマップ全体にあります。グローバル変数とマルチファイルカップリング...さて、</soapbox>症状の治療に移りましょう。

問題1:DOMがロードされる前にノックアウトをバインドする

applyBindingsをdomreadyコールバックに入れます。

jQuery(function($) {
   ko.applyBindings(viewModel);
});

問題2:foreachが遅い

データセットが大きい場合、foreachバインディングのノックアウトは非常に遅くなります。このSOの質問で説明されているように、jQueryテンプレートを試して、foreachをテンプレート内に移動できます。時間が約3秒に短縮されているようです。

現在のforeachで問題なくレンダリングされるように見えるため、これが必要な理由はよくわかりません。ノックアウトがバックグラウンドで魔法を実行している間、foreachが完了した後に発生します。

補足:フリップを観察可能な配列に入れる必要がありますか?現在のコードでは何も必要ないので、後でそれを使用するつもりだと思います。そうでない場合は、それを取り出してください。パフォーマンスに役立ちます(ただし、この問題は解決されません)。

乾杯、これがお役に立てば幸いです。

于 2012-08-29T17:23:08.150 に答える
2

foreachこれは、バインディングとChromeの間のある種の奇妙なレンダリングのバグです。の前にテンプレートに文字を追加してみたところdiv、遅延が修正されました(ただし、レイアウトが台無しになりました)。

これを修正する良い方法は、以外のものを使用することですforeach。私のrepeatバインディングはここでうまく機能し、遅延の問題を解決します。

これがあなたのコードのそのセクションですrepeat

<div class="condListHolder" style="width:558px">
    <div class="cond2" title="Click to flip" data-bind="repeat: flips">
        <div class="piece obm" data-bind="
          style: { backgroundPosition: getLeftValue($index) + ' ' + getTopValue($index) },
          attr: {cond: $item().cond, id: $item().Id },
          click: setClick "></div>
    </div>
</div>

repeatのobservableを使用しないため、と関数を変更して、の後に括弧を$index削除する必要があります。getTopValuegetLeftValue()index

于 2012-08-29T23:23:54.567 に答える
1

また、foreachループによって呼び出されるコードの合理化も検討する必要があります。getLeftValueとメソッドを呼び出す頻度はわかりませんが、getTopValue最適化されていません。

  • 同じ結果が得られる関数呼び出しを制限してみてください。ローカル変数を使用してキャッシュするのは安価なので
  • 大きなループで文字列を連結しないでください。これは、配列を使用して文字列を結合するよりもはるかに低速です。

2つの機能を最適化してみました。少なくともいくつかの改善が見られるはずです。

getLeftValue: function (index) {

    var position = 0,
        realIndex = index(),
        currentLine = div(realIndex, 25);


    if (currentLine > 0)
        return ["-", (realIndex - (currentLine * 25)) * 20, "px"].join("");
    else
        return ["-", realIndex, "px"].join("");
},

getTopValue: function (index) {

    return ["-",(div(index(), 25)) * 20,"px"].join("");
}
于 2012-08-30T08:16:11.593 に答える