1

Knockout 2.3.0を使用したIEメモリ リークが発生するという問題があります。画面に表示される結果のリストがあり、その結果セットにはページング機能があります。ページングされた結果の次のセットを取得するために、コントローラーへの AJAX コールバックがあります。最初のページを画面に最初にバインドするとき、IE のメモリ負荷は約 150Mb ですが、各ページで約 50Mb から 100Mb が追加されます。この問題は、Chrome または FireFox では発生しません。

この問題はよくあることのようで、次のような多くの例を調べまし

var householdViewModel = ko.observable();

var HouseholdViewModel = function (data) {
    ko.mapping.fromJS(data, mapping, this);    
};

var AccountViewModel = function (data) {
    ko.mapping.fromJS(data, mapping, this);
};

var mapping = {
    'Households': {
        create: function(options) {
            return new HouseholdViewModel(options.data);
        }
    },
    'Accounts': {
        create: function (options) {
            return new AccountViewModel(options.data);
        }
    }
};

次のような AJAX 呼び出しを行うために MVC フレームワークを使用しています。

@Ajax.ActionLink(">", "PageInfo", new {pageOption = "Next"}, new AjaxOptions {UpdateTargetId = "SearchResults", HttpMethod = "GET", OnBegin = "OnBeginAjaxListManipulation", OnComplete = "OnCompleteAjaxListManipulation"}, new {@class = "textNavigationElement"})

次のようなコールバック JS メソッドを使用します。

    function OnCompleteAjaxListManipulation() {
        //ko.cleanNode(document.getElementById("SearchResults"));
        var HHVM = { Households: ko.mapping.fromJS(@Html.Raw(Json.Encode(Model.Households))) };
        householdViewModel(new HouseholdViewModel(HHVM));
        //ko.applyBindings(householdViewModel, document.getElementById("SearchResults"));
    }

Info.cshtml というページと、検索結果を表示する results.cshtml という部分ページがあることを意味する必要があると思います。情報ページで、次の呼び出しを行います。

    var HHVM = { Households: ko.mapping.fromJS(@Html.Raw(Json.Encode(Model.Households))) };
    householdViewModel(new HouseholdViewModel(HHVM));
    ko.applyBindings(householdViewModel, document.getElementById("SearchResults"));

検索結果は、最初のページでは問題なく表示されますが、2 ページ目では何も表示されません。JS コールバックに 2 つ目の applyBindings を追加すると機能しますが、メモリ リークの問題が発生します。私はこれを理解できません。どんな助けでも大歓迎です。

ジョシュ

4

1 に答える 1

0

観測可能な配列を手動で制御することで修正しましたが、これはおそらくあなたが行うべき方法です。まず、モデルを次のように変更します。

var Households = ko.observableArray(HouseholdViewModel);

var HouseholdViewModel = function (data) {
    ko.mapping.fromJS(data, mapping, this);    
};

var AccountViewModel = function (data) {
    ko.mapping.fromJS(data, mapping, this);
};

var mapping = {
    'Households': {
        create: function(options) {
            return new HouseholdViewModel(options.data);
        }
    },
    'Accounts': {
        create: function (options) {
            return new AccountViewModel(options.data);
        }
    }
};

次に、呼び出された Ajax がトリガーされる方法を変更し、UpdateTargetId を削除して、これを自分で制御することにしました。コードは次のようになります。

@Ajax.ActionLink(">>", "PageInfo", new {pageOption = "Last"}, new AjaxOptions {HttpMethod = "GET", OnBegin = "OnBeginAjaxListManipulation", OnComplete = "OnCompleteAjaxListManipulation", OnSuccess = "BindModel"}, new {@class = "textNavigationElement"}) 

    function BindModel(e) {
        var isBound = !!ko.dataFor(document.getElementById("SearchResults"));
        if (isBound)
            Households.removeAll();

        $.each(e.Households, function (index, value) {
            var hh = new HouseholdViewModel(value);
            Households.push(hh);
        });

        if (!isBound)
            ko.applyBindings(Households, document.getElementById("SearchResults"));
    }

以上です!その結果、モデルがバインドされるたびに、監視可能な配列がクリアされ、アイテムが読み取られます。監視可能な配列をページにバインドしていたため、ko.CleanNode を実行して再バインドする必要はありません :-)

これが他の誰かを助けることができることを願っています。

于 2013-10-21T19:21:45.570 に答える